12

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

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

在这个例子中,编译错误在第三行。

4

4 回答 4

11

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

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

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

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

更新:jrudolph 建议此行为基于 JVM 中可用的操作,特别是仅实现全字和双字运算符。因此,要对字节和短裤进行操作,必须将它们转换为 int。

于 2008-09-17T09:16:38.410 回答
7

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

byte 和 short 类型的操作数在交给操作员之前会自动提升为 int

因此,在您的示例中,aand在交给 + 运算符之前b都转换为 a 。int两个ints 相加的结果也是一个int。然后尝试将其分配int给一个byte值会导致错误,因为存在潜在的精度损失。通过显式转换结果,您是在告诉编译器“我知道我在做什么”。

于 2008-09-17T09:26:49.167 回答
2

我认为,问题在于 JVM 仅支持两种类型的堆栈值:字长和双字长。

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

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

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

于 2008-09-17T09:34:00.507 回答
1

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

a + b

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

(int)a + (int)b

这个表达式是 int 类型的。在将 int 值分配给字节变量时给出错误显然是有意义的。

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

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

于 2008-09-17T10:15:20.563 回答