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

时间:2015-08-14 08:18:53

标签: 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);

为什么第3行是对的?看起来类型不正确,我应该得到第4行的错误。

Live example on ideone

2 个答案:

答案 0 :(得分:8)

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

如果您为b5b4(例如b5)选择了不同的值,那么您在第3行也会收到错误:

100

Live on ideone

这是展示这一点的东西,将编译

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);

这是反汇编:

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存储在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);

答案 1 :(得分:-1)

  

JVM如何处理关键字“final”?   运行时的JVM不知道这个修饰符。 Compilator确实。

你的问题不是最终的,要消除错误,请执行以下操作:

b3=(byte)(b1+b2);   // line isn't invalid now

前面定义的最终变量的一次赋值是一个有效的陈述本身。

第3行 - 编译器只是将您的值内联为整数常量。

   L4
    LINENUMBER 30 L4
    BIPUSH 10
    ISTORE 4

第4行 - 编译器不能这样做。

   L5
    LINENUMBER 31 L5
    ILOAD 1
    ILOAD 2
    IADD
    I2B
    ISTORE 3

阅读下一篇: http://www.javatpoint.com/final-keyword