【问题标题】:Is addition of byte converts to int because of java language rules or because of jvm?由于java语言规则或jvm,添加字节转换为int?
【发布时间】:2020-07-27 16:34:25
【问题描述】:
byte a = 1;
byte b = 1;
byte c = a + b;

抛出错误:可能损失精度

byte subt = a_s - a_b;
                ^
  required: byte
  found:    int

这种行为是否与 jvm 有关或它是用 java 语言定义的。

编辑:如果它是用 java 语言定义的,那么是因为要记住 jvm 吗?

表示如果java支持byte数据类型那么为什么operation on byte结果int

【问题讨论】:

标签: java type-conversion byte operation type-promotion


【解决方案1】:

如果java支持字节数据类型,那么为什么对字节的操作结果是int

因为 Java 虚拟机就是这样设计的。没有指令集可以对字节类型执行操作。而int 类型的指令集用于booleanbytecharshort 类型的操作。

来自JVM Spec - Section 2.11.1

编译器使用 Java 虚拟机指令对大量 byteshort 类型的文字值进行编码,这些指令在编译时或运行时将这些值符号扩展为 int 类型的值。 booleanchar 类型的文字值的加载使用在编译时或运行时将文字零扩展为 int 类型的值的指令进行编码。 [..]。因此,对实际类型 booleanbytecharshort 的值的大多数操作都可以通过对计算类型 int 的值进行操作的指令正确执行。

该部分也说明了这背后的原因:

鉴于 Java 虚拟机的单字节操作码大小,将类型编码为操作码会对其指令集的设计造成压力。如果每个类型化的指令都支持 Java 虚拟机的所有运行时数据类型,那么就会有比byte 表示的指令更多。 [...] 可以根据需要使用单独的指令在不受支持和支持的数据类型之间进行转换。

有关所有指令集可用于各种类型的详细信息,您可以浏览该部分中的表格。

还有一个表指定实际类型到JVM计算类型的映射:

【讨论】:

  • +1 当 JIT 将代码优化为本机代码时,它可以使用它喜欢的任何类型。它不必是 int 类型。
  • Java 是否仍然不能将它们转换为int,执行操作,然后将它们转换回byte? JLS 规范似乎更适用,尽管这可以解释这部分 JLS 背后的原因。
  • @PeterLawrey 本机代码是否与 Java 相关?我的意思是这可以是一种不同的语言。我对吗?对 JIT 优化知之甚少。
  • @Dukeling。对 int 类型执行的二进制操作只会产生 int 类型。最终结果不是字节类型,因为结果可能不适合它。 JLS 可能不太适用,因为它没有解释 JVM 的内部结构,我猜这是 OP 想要的。
  • @RohitJain 本机代码将相关并产生相同的结果。 如何 由 JIT 决定。如果 byte 加法由于某种原因(我怀疑)更快,它可以使用它。
【解决方案2】:

JLS 5.6.2: Binary Numeric Promotion 覆盖它:

加宽原语转换(第 5.1.2 节)适用于转换以下规则中指定的一个或两个操作数:

  • 如果任一操作数的类型为double,则另一个将转换为double

  • 否则,如果任一操作数的类型为float,则将另一个转换为float

  • 否则,如果任一操作数的类型为long,则将另一个转换为long

  • 否则,两个操作数都转换为int类型。

【讨论】:

    【解决方案3】:

    编译器正在做正确的事情。因为 (a + b) 可以超出可以保存在字节变量中的最大值。如果你告诉编译器 a、b 的值不会通过使用 'final' 关键字而改变,它就不会再抱怨了。

    final byte a = 1;
    final byte b = 1;
    byte c = a + b;
    

    【讨论】:

    • 字节 c = a + b;结果出错... b+=a;编译成功。为什么?
    • 复合运算符 (+=) 将结果转换为 b = (byte) (b + a);
    【解决方案4】:

    是的,这是语言规范。

    加法(+)运算符。在添加时,'a' 被转换(隐式转换)为 int 类型, b 也可以输入int。因此result 隐含的类型为int

    - 运算符也一样。

    【讨论】:

      【解决方案5】:

      编译器是对的,将变量声明为final或强制转换为字节:

      byte b =  1;
      byte c =  22;
      byte a = (byte) (b + c);
      

      JAVA : byte+byte = int

      :)

      【讨论】:

      • 小心下溢或上溢。
      【解决方案6】:

      在对任何操作数进行算术运算时,结果以这种形式存储 MAX(int,operand1 type,operand2 type,...operandN type) 前任: byte a=10; byte b=20; byte c=a+b;

      那么a+b的结果会以MAX(int,operand1 type,operand2 type,...operandN type)的形式存储 在这种情况下 MAX(int,byte,byte) 最大值是 int,它是最大值,所以 c 将具有 int 值,但 c 已被声明为 byte,我们不能将 int(bigger) 值存储到 byte(smaller) 中。这同样适用于每个算术运算符。

      这就是错误提示的原因 错误:不兼容的类型:从 int 到 byte

      的可能有损转换

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-23
        • 2011-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多