为什么我不能添加两个字节并得到一个int,而我可以添加两个最后一个字节得到一个字节?

2022-09-01 09:47:40
public class Java{
    public static void main(String[] args){
        final byte x = 1;
        final byte y = 2;
        byte z = x + y;//ok
        System.out.println(z);

        byte a = 1;
        byte b = 2;
        byte c = a + b; //Compiler error
        System.out.println(c);
    }
}

如果表达式涉及任何整数大小或更小的表达式的结果始终是整数,即使两个字节的总和适合一个字节。

为什么当我们添加两个适合一个字节的最终字节时会发生这种情况?没有编译器错误。


答案 1

从 JLS 5.2 赋值转换

此外,如果表达式是字节、短、字符或 int 类型的常量表达式 (§15.28):- 如果变量的类型为 byte、short 或 char,并且常量表达式的值可在变量的类型中表示,则可以使用缩小基元转换。

简而言之,表达式的值(在编译时是已知的,因为它是一个常量表达式)可以用字节变量的类型来表示。

考虑您的表达方式

 final byte x = 1;
 final byte y = 2;
 byte z = x + y;//This is constant expression and value is known at compile time

因此,当求和适合字节时,它不会引发编译错误。

现在,如果您这样做

final byte x = 100;
final byte y = 100;
byte z = x + y;// Compilation error it no longer fits in byte

答案 2
byte z = x + y;  // x and y are declared final

这里,由于 和 被声明,所以 在编译时表达式的值是已知的,它是固定的,不能变化。因此,您不需要显式地对其进行类型转换xyfinalRHS(1 + 2 = 3)

byte c = a + b;   // a and b are not declared final

然而,在这种情况下,和 的值不被宣布为最终值。因此,表达式的值在编译时是未知的,而是在运行时计算的。因此,您需要进行显式转换。ab


但是,即使在第一个代码中,如果的值出来超出范围,它将无法编译。a + b-128 to 127

final byte b = 121;
final byte a = 120;
byte x = a + b;  // This won't compile, as `241` is outside the range of `byte`

final byte b1 = 12;
final byte a1 = 12;
byte x1 = a1 + b1;  // Will Compile. byte can accommodate `24`