先来看下代码,和运行结果
package com.zsq;
import java.lang.reflect.Field;
public class Test {
final int a = 3;
final Integer b = 3;
public static void main(String[] aa) throws NoSuchFieldException, IllegalAccessException {
Test s = new Test();
Field f = Test.class.getDeclaredField("a");
f.setAccessible(true);
f.set(s, 20);
System.out.println(s.a + 2);
Field fb = Test.class.getDeclaredField("b");
fb.setAccessible(true);
fb.set(s, 20);
System.out.println(s.b + 2);
}
}
结果说明b被重置成功了,但是a没有重置成功。但是按照JLS中说的final 修饰的field 是可以通过反射修改的。为什么Integer 类型可以被修改而int 类型的不能被修改呢?(实际上下图的第二段给出了答案)
神奇的是通过debug 可以看到int 和Integer类型的field 都是被修改成功了的。
为什么输出结果不正确呢?
养成一个良好的习惯多看字节码,从下面的字节码中可以看到 System.out.println(s.a + 2); 这句代码被编译成了。也就是说javac 编译器将一个final 的int 变量优化成了iconst_3。所以…
39: iconst_3
40: iconst_2
41: iadd
42: invokevirtual #13 // Method java/io/PrintStream.println:(I)V