【问题标题】:Java: why do I receive the error message "Type mismatch: cannot convert int to byte"Java:为什么我会收到错误消息“类型不匹配:无法将 int 转换为字节”
【发布时间】:2010-09-10 00:45:07
【问题描述】:

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

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

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

【问题讨论】:

  • IIRC JVM 将字节和短裤存储为整数,因此使用这两种数据类型通常没有什么好处。当然,我意识到您正在做的事情比您的示例复杂得多,并且可能有很好的理由。

标签: java type-conversion byte type-mismatch


【解决方案1】:

虽然算术运算符被定义为对任何数值类型进行运算,但根据 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。

【讨论】:

  • 我猜是因为性能。在某些 CPU 中,使用小于 cpu 寄存器的操作数可能会更昂贵。可能它甚至使用 32 位 int 来存储 byte 和 short,以保持它们在内存中对齐。
  • 因为我发现 - 操作是在 CPU 寄存器中执行的,但是它们是 32 位对齐的。你也不能对字符执行 + 运算符
  • byte c = (byte)(a + b);转换后,此表达式将如下所示 byte c = 57 其中 57 是字节类型。但是,由于数字提升声明所有字节、短和字符文字都转换为 int,这个字节 57 将被提升为 int 57。所以从这个意义上说,编译器仍然应该给出一个错误,但它没有。为什么?
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    然后他们可能决定只需要一个操作来处​​理堆栈上的字长整数。所以字节码级别只有 iadd、imul 等(没有字节和短的运算符)。

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

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

    【讨论】:

      【解决方案4】:

      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 指出,他的例子在正常有符号算术下也给出了错误的例子。为了便于理解的算术,我们需要任意精度。

      【讨论】:

        猜你喜欢
        • 2020-07-11
        • 2017-01-04
        • 1970-01-01
        • 1970-01-01
        • 2016-03-20
        • 1970-01-01
        • 2022-06-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多