使用的是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