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

如果声明byte或short类型的变量并尝试对这些变量执行算术运算,则会收到错误“Type mismatch:can int int int to short”(或相应的“Type mismatch:not int int int to byte”)。

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

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

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

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

 字节a = 23;
字节b = 34;
字节c =(字节)(a + b); 

这是真正的Java专家的后续问题:为什么? 字节和短字类型是完美的数字类型。 为什么Java不允许对这些类型进行直接算术运算? (答案不是“精度损失”,因为没有明显的理由首先转换为int。)

更新:jrudolph表明此行为基于JVM中可用的操作,具体而言,仅实现了全字和双字运算符。 因此,对于字节和短路的运算符,它们必须转换为int。

您的后续问题的答案如下:

在传递给运算符之前,byte和short类型的操作数会自动提升为int

因此,在您的示例中, ab在被传递给+运算符之前都被转换为int 。 将两个int加在一起的结果也是一个int 。 尝试将该int分配给byte值会导致错误,因为可能会丢失精度。 通过显式地转换结果,您告诉编译器“我知道我在做什么”。

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

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

因此,作为这些操作的结果,您将获得一个int值,Java无法安全地将其转换回较小的字节和短数据类型。 因此,它们强制您进行转换以将值缩小到字节/短。

但最终你是对的:例如,这种行为与整数的行为不一致。 您可以毫无问题地添加两个整数,如果结果溢出则不会出现错误。

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

 a + b 

其中a和b的类型为byte。 这是以下的简写:

 (int)a + (int)b 

此表达式的类型为int。 将int值赋给字节变量时给出错误显然是有意义的。

为什么要以这种方式定义语言? 假设a为60且b为70,则a + b为-126 – 整数溢出。 作为一个更复杂的表达式的一部分,预计会导致int,这可能会成为一个困难的bug。 限制使用字节和短数据存储,文件格式/网络协议和益智游戏的常量。

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