Java:为什么我收到错误消息“类型不匹配:不能将int转换为byte”

时间:2023-01-24 22:25:24

If you declare variables of type byte or short and attempt to perform arithmetic operations on these, you receive the error "Type mismatch: cannot convert int to short" (or correspondingly "Type mismatch: cannot convert int to byte").

如果您声明类型为byte或short的变量并尝试对它们执行算术操作,您将收到错误“类型不匹配:不能将int转换为short”(或相应的“类型不匹配:不能将int转换为byte”)。

byte a = 23;
byte b = 34;
byte c = a + b;

In this example, the compile error is on the third line.

在本例中,编译错误位于第三行。

4 个解决方案

#1


8  

Although the arithmetic operators are defined to operate on any numeric type, according the Java language specification (5.6.2 Binary Numeric Promotion), operands of type byte and short are automatically promoted to int before being handed to the operators.

虽然算术运算符被定义为对任何数字类型进行操作,但是根据Java语言规范(5.6.2二进制数字升级),类型为byte的操作数和短的操作数在移交给操作符之前会自动升级为int。

To perform arithmetic operations on variables of type byte or short, you must enclose the expression in parentheses (inside of which operations will be carried out as type int), and then cast the result back to the desired type.

要对类型为byte或short的变量执行算术操作,必须将表达式括在圆括号中(在圆括号中操作将作为类型int执行),然后将结果转换回所需的类型。

byte a = 23;
byte b = 34;
byte c = (byte) (a + b);

Here's a follow-on question to the real Java gurus: why? The types byte and short are perfectly fine numeric types. Why does Java not allow direct arithmetic operations on these types? (The answer is not "loss of precision", as there is no apparent reason to convert to int in the first place.)

对于真正的Java大师,这里有一个后续问题:为什么?字节和短类型是非常好的数字类型。为什么Java不允许对这些类型进行直接的算术操作?(答案不是“精度损失”,因为首先没有明显的理由将其转换为int类型。)

Update: jrudolph suggests that this behavior is based on the operations available in the JVM, specifically, that only full- and double-word operators are implemented. Hence, to operator on bytes and shorts, they must be converted to int.

更新:jrudolph建议这种行为基于JVM中可用的操作,具体来说,只有完全和双字的操作符被实现。因此,要对字节和短裤进行操作,必须将它们转换为int。

#2


5  

The answer to your follow-up question is here:

你的后续问题的答案在这里:

operands of type byte and short are automatically promoted to int before being handed to the operators

类型字节和短的操作数在交给操作符之前自动升级为int。

So, in your example, a and b are both converted to an int before being handed to the + operator. The result of adding two ints together is also an int. Trying to then assign that int to a byte value causes the error because there is a potential loss of precision. By explicitly casting the result you are telling the compiler "I know what I am doing".

在你的例子中,a和b在被赋给+运算符之前都被转换成int。将两个ints加在一起的结果也是一个int,试图将这个int分配给一个字节值导致错误,因为它可能会丢失精度。通过显式地转换结果,您是在告诉编译器“我知道我在做什么”。

#3


2  

I think, the matter is, that the JVM supports only two types of stack values: word sized and double word sized.

我认为,问题是JVM只支持两种类型的栈值:字大小和双字大小。

Then they probably decided that they would need only one operation that works on word sized integers on the stack. So there's only iadd, imul and so on at bytecode level (and no operators for bytes and shorts).

然后,他们可能决定只需要一个操作,就可以在堆栈上使用word大小的整数。所以只有iadd, imul等在字节码级别(没有字节和短裤的操作符)。

So you get an int value as the result of these operations which Java can't safely convert back to the smaller byte and short data types. So they force you to cast to narrow the value back down to byte/short.

因此,由于这些操作,您将得到一个int值,而Java无法安全地将其转换回更小的字节和更短的数据类型。因此,它们迫使您将值转换为byte/short。

But in the end you are right: This behaviour is not consistent to the behaviour of ints, for example. You can without problem add two ints and get no error if the result overflows.

但最终你是对的:例如,这种行为与小型企业的行为不一致。您可以毫无问题地添加两个ints,并且在结果溢出时不会得到错误。

#4


1  

The Java language always promotes arguments of arithmetic operators to int, long, float or double. So take the expression:

Java语言总是将算术运算符的参数提升为int、long、float或double。所以把表达式:

a + b

where a and b are of type byte. This is shorthand for:

其中a和b属于类型字节。这是缩写:

(int)a + (int)b

This expression is of type int. It clearly makes sense to give an error when assigning an int value to a byte variable.

这个表达式是int类型的,当给一个字节变量赋int值时,它显然是有意义的。

Why would the language be defined in this way? Suppose a was 60 and b was 70, then a+b is -126 - integer overflow. As part of a more complicated expression that was expected to result in an int, this may become a difficult bug. Restrict use of byte and short to array storage, constants for file formats/network protocols and puzzlers.

为什么要用这种方式来定义语言?假设a是60,b是70,那么a+b是-126 -整数溢出。作为预期会导致int的更复杂表达式的一部分,这可能成为一个困难的bug。限制使用字节和短到数组存储、文件格式/网络协议的常量和解码器。

There is an interesting recording from JavaPolis 2007. James Gosling is giving an example about how complicated unsigned arithmetic is (and why it isn't in Java). Josh Bloch points out that his example gives the wrong example under normal signed arithmetic too. For understandable arithmetic, we need arbitrary precision.

有一个有趣的记录来自JavaPolis 2007。James Gosling举了一个例子,说明无符号算术有多复杂(以及为什么它不在Java中)。Josh Bloch指出,他的例子也给出了正常有符号算术的错误例子。对于可理解的算术,我们需要任意的精度。

#1


8  

Although the arithmetic operators are defined to operate on any numeric type, according the Java language specification (5.6.2 Binary Numeric Promotion), operands of type byte and short are automatically promoted to int before being handed to the operators.

虽然算术运算符被定义为对任何数字类型进行操作,但是根据Java语言规范(5.6.2二进制数字升级),类型为byte的操作数和短的操作数在移交给操作符之前会自动升级为int。

To perform arithmetic operations on variables of type byte or short, you must enclose the expression in parentheses (inside of which operations will be carried out as type int), and then cast the result back to the desired type.

要对类型为byte或short的变量执行算术操作,必须将表达式括在圆括号中(在圆括号中操作将作为类型int执行),然后将结果转换回所需的类型。

byte a = 23;
byte b = 34;
byte c = (byte) (a + b);

Here's a follow-on question to the real Java gurus: why? The types byte and short are perfectly fine numeric types. Why does Java not allow direct arithmetic operations on these types? (The answer is not "loss of precision", as there is no apparent reason to convert to int in the first place.)

对于真正的Java大师,这里有一个后续问题:为什么?字节和短类型是非常好的数字类型。为什么Java不允许对这些类型进行直接的算术操作?(答案不是“精度损失”,因为首先没有明显的理由将其转换为int类型。)

Update: jrudolph suggests that this behavior is based on the operations available in the JVM, specifically, that only full- and double-word operators are implemented. Hence, to operator on bytes and shorts, they must be converted to int.

更新:jrudolph建议这种行为基于JVM中可用的操作,具体来说,只有完全和双字的操作符被实现。因此,要对字节和短裤进行操作,必须将它们转换为int。

#2


5  

The answer to your follow-up question is here:

你的后续问题的答案在这里:

operands of type byte and short are automatically promoted to int before being handed to the operators

类型字节和短的操作数在交给操作符之前自动升级为int。

So, in your example, a and b are both converted to an int before being handed to the + operator. The result of adding two ints together is also an int. Trying to then assign that int to a byte value causes the error because there is a potential loss of precision. By explicitly casting the result you are telling the compiler "I know what I am doing".

在你的例子中,a和b在被赋给+运算符之前都被转换成int。将两个ints加在一起的结果也是一个int,试图将这个int分配给一个字节值导致错误,因为它可能会丢失精度。通过显式地转换结果,您是在告诉编译器“我知道我在做什么”。

#3


2  

I think, the matter is, that the JVM supports only two types of stack values: word sized and double word sized.

我认为,问题是JVM只支持两种类型的栈值:字大小和双字大小。

Then they probably decided that they would need only one operation that works on word sized integers on the stack. So there's only iadd, imul and so on at bytecode level (and no operators for bytes and shorts).

然后,他们可能决定只需要一个操作,就可以在堆栈上使用word大小的整数。所以只有iadd, imul等在字节码级别(没有字节和短裤的操作符)。

So you get an int value as the result of these operations which Java can't safely convert back to the smaller byte and short data types. So they force you to cast to narrow the value back down to byte/short.

因此,由于这些操作,您将得到一个int值,而Java无法安全地将其转换回更小的字节和更短的数据类型。因此,它们迫使您将值转换为byte/short。

But in the end you are right: This behaviour is not consistent to the behaviour of ints, for example. You can without problem add two ints and get no error if the result overflows.

但最终你是对的:例如,这种行为与小型企业的行为不一致。您可以毫无问题地添加两个ints,并且在结果溢出时不会得到错误。

#4


1  

The Java language always promotes arguments of arithmetic operators to int, long, float or double. So take the expression:

Java语言总是将算术运算符的参数提升为int、long、float或double。所以把表达式:

a + b

where a and b are of type byte. This is shorthand for:

其中a和b属于类型字节。这是缩写:

(int)a + (int)b

This expression is of type int. It clearly makes sense to give an error when assigning an int value to a byte variable.

这个表达式是int类型的,当给一个字节变量赋int值时,它显然是有意义的。

Why would the language be defined in this way? Suppose a was 60 and b was 70, then a+b is -126 - integer overflow. As part of a more complicated expression that was expected to result in an int, this may become a difficult bug. Restrict use of byte and short to array storage, constants for file formats/network protocols and puzzlers.

为什么要用这种方式来定义语言?假设a是60,b是70,那么a+b是-126 -整数溢出。作为预期会导致int的更复杂表达式的一部分,这可能成为一个困难的bug。限制使用字节和短到数组存储、文件格式/网络协议的常量和解码器。

There is an interesting recording from JavaPolis 2007. James Gosling is giving an example about how complicated unsigned arithmetic is (and why it isn't in Java). Josh Bloch points out that his example gives the wrong example under normal signed arithmetic too. For understandable arithmetic, we need arbitrary precision.

有一个有趣的记录来自JavaPolis 2007。James Gosling举了一个例子,说明无符号算术有多复杂(以及为什么它不在Java中)。Josh Bloch指出,他的例子也给出了正常有符号算术的错误例子。对于可理解的算术,我们需要任意的精度。