由于java语言规则或jvm,是否将字节转换为int?

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支持byte数据类型,那么为什么对byte的操作会产生int

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

从JVM规范 – 第2.11.1节 :

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

其背后的原因也在该部分中说明:

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

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

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

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

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

JLS 5.6.2:二进制数字促销包括:

应用扩展基元转换(第5.1.2节)来转换由以下规则指定的一个或两个操作数:

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

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

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

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

是的,这是语言规范。

加法(+)运算符。 添加时, 'a'转换(隐式转换)为int类型,b也转换为int类型。 因此result隐式为int类型。

同样适用于-运营商。

在对任何操作数进行算术运算时,结果以MAX(int,operand1类型,operand2类型,… operandN类型)forms存储Ex: byte a=10; byte b=20; byte c=a+b; byte a=10; byte b=20; byte c=a+b;

然后a + b的结果将以MAX(int,operand1类型,operand2类型,… operandN类型)的forms存储,在这种情况下MAX(int,byte,byte)最大值为int,这是最大值所以c将具有int值但c已被声明为byte,并且我们不能将int(更大)值存储到byte(更小)中。 这同样适用于每个算术运算符。

这就是错误说错误的原因:不兼容的类型:从int到byte的可能有损转换

编译器是正确的,将变量声明为final或强制转换为byte:

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

JAVA:byte + byte = int

🙂