为什么添加最终字节会产生一个字节,但添加非最终字节会产生一个int?

GsM*_*GsM 2 java jvm final

byte b1=1,b2=2,b3,b6; 
final byte b4=4,b5=6; 
b6=b4+b5;    // line3
b3=b1+b2;    // line4: error: incompatible types: possible lossy conversion from int to byte
System.out.println(b3+b6);
Run Code Online (Sandbox Code Playgroud)

为什么第3行是对的?似乎类型不正确,我应该得到第4行的错误.

关于ideone的实例

T.J*_*der 8

错误发生在第4行而不是第3行,因为编译器知道final变量的值,但不知道非final变量的值.编译器看到final并且变量在使用之前已经明确赋值为常量值,并且作为变量final,该值无法更改.由于编译器知道这些值,因此它知道值10(b4+b5)的转换没有丢失.实际上,它们实际上是常量而且你正在做b6=10 - 如果你看一下如果我们删除第4行并调整第6行所生成的字节码,我们就会发现这正是编译器所做的:完全优化b4b5完全.

如果为b4b5(100例如)选择了不同的值,那么第3行也会出现错误:

byte b1=1,b2=2,b3,b6; 
final byte b4=100,b5=100; 
b6=b4+b5;  // line3 error: incompatible types: possible lossy conversion from int to byte
b3=b1+b2;  // line4 error: incompatible types: possible lossy conversion from int to byte
System.out.println(b3+b6);
Run Code Online (Sandbox Code Playgroud)

生活在想法上

这是展示这个的东西,将编译

byte b1=1,b2=2,b3,b6; 
final byte b4=4,b5=6; 
b6=b4+b5;  // line3
//b3=b1+b2;  // line4
//System.out.println(b3+b6);
System.out.println(b6);
Run Code Online (Sandbox Code Playgroud)

这是反汇编:

public static void main(java.lang.String[]) throws java.lang.Exception;
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: bipush        10
       6: istore        4
       8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      11: iload         4
      13: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      16: return

请注意

4: bipush        10
6: istore        4

...存储字面值10 b6.