7

分析这个简单类的字节码,我得出的结论是编译器没有保留任何关于局部变量的信息final。不过这看起来很奇怪,因为我相信 HotSpot 编译器实际上可以使用这些信息进行优化。

代码

public static void main(String[] args)
{
    final int i = 10;
    System.out.println(i);
}

字节码

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=2, locals=2, args_size=1
     0: bipush        10
     2: istore_1      
     3: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
     6: bipush        10
     8: invokevirtual #22                 // Method java/io/PrintStream.println:(I)V
    11: return        
  LineNumberTable:
    line 7: 0
    line 8: 3
    line 9: 11
  LocalVariableTable:
    Start  Length  Slot  Name   Signature
        0      12     0  args   [Ljava/lang/String;
        3       9     1     i   I

除了节省磁盘空间之外,是否有任何特定原因保留局部变量的访问标志?因为对我来说,存在似乎final是变量的一个相对重要的属性。

4

1 回答 1

8

字节码中final不存在修饰符,但编译器已经使用此信息进行了一些优化。尽管您的示例没有显示它,但编译器可能会final在方法的字节码表示中内联变量的值,从而获得更好的性能。类似下面的内容可以显示差异:

public int addFinal() {
    final int i = 10;
    final int j = 10;
    return i + j;
}

public int addNonFinal() {
    int i = 10;
    int j = 10;
    return i + j;
}

生成的字节码分别用于每种方法:

// addFinal
bipush 10
istore_1
bipush 10
istore_2
bipush 20
ireturn


// addNonFinal
bipush 10
istore_1
bipush 10
istore_2
iload_1
iload_2
iadd
ireturn
于 2015-05-10T12:39:30.453 回答