使用的是oracle jdk7具体版本是: (build 1.7.0_01-b08)
1.方法作用于的final变量:
源码:
public void methodScopeFinal(){
final int age = 22;
final String firstName = "xu";
int nextAge = age+1;
String name = firstName+"guoping";
}
javap -c反编译得到的jvm指令, 可以看出jvm指令中没有包含对两个final变量(方法作用于中的final成为变量是合适的,因为很多时候需要根据不同的传入参数赋予不同的值)的定义,只有对age+1和firstName+"guoping"的最后结果赋值。
public void methodScopeFinal();
Code:
0: bipush 23
2: istore_3
3: ldc #2 // String xuguoping
5: astore 4
7: return
------------------------------------------------------------------------------------------------------------------------------------------------
作为对比看下去掉final变量后的指令:
public void methodScopeFinal(){
int age = 22;
String firstName = "xu";
int nextAge = age+1;
String name = firstName+"guoping";
}
没有使用final后的指令要多出很多,包括对age和firstName两个变量的定义和赋值以及后面的加法指令和字符串连接运算指令。
public void methodScopeFinal();
Code:
0: bipush 22
2: istore_1
3: ldc #2 // String xu
5: astore_2
6: iload_1
7: iconst_1
8: iadd
9: istore_3
10: new #3 // class java/lang/StringBuilder
13: dup
14: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
17: aload_2
18: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: ldc #6 // String guoping
23: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
26: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
29: astore 4
31: return
}
=====================================================================================
final变量定义类:
public class FinalClassVariableTest
{
public final int age = 22;
public final int anotherAge = getAnotherAge();
public final String firstName = "xu";
public int getAnotherAge(){
return 5;
}
}
final变量使用类:FinalClassVariableTest
public void testClassFinal(){
FinalClassVariable fcVariable = new FinalClassVariable();
int age = fcVariable.age;
int anotherAge = fcVariable.anotherAge;
String name = fcVariable.firstName;
}
从
FinalClassVariableTest 上述
方法的指令可以看出对FinalClassVariable 对象中final int和string在指令中不是通过变量去引用而是直接保存对应的常量值:22和"xu",
因此应该注意:如果修改了primitive和string类型的final变量值,不仅要编译单个类最好要把整个工程都全部编译。否则会导致引用到final变量的地方还是修改以前的常量值。
public static final情形编译器做相同的处理。
上面method对应的jvm指令:
public void testClassFinal();
Code:
0: new #2 // class FinalClassVariable
3: dup
4: invokespecial #3 // Method FinalClassVariable."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method java/lang/Object.getClass:()Ljava/lang/Class;
12: pop
13: bipush 22
15: istore_2
16: aload_1
17: getfield #5 // Field FinalClassVariable.anotherAge:I
20: istore_3
21: aload_1
22: invokevirtual #4 // Method java/lang/Object.getClass:()Ljava/lang/Class;
25: pop
26: ldc #6 // String xu
28: astore 4
30: return