有的时候,咱们须要修改一个变量的值,但变量也许存在于 Jar 包中或其余位置,致使咱们不能从代码层面进行修改,因而咱们就用到了下面的场景,经过反射来进行修改变量的值。java
class Bean{ private static final Integer INT_VALUE = 100; }
System.out.println(Bean.INT_VALUE); Field field = Bean.class.getField("INT_VALUE"); //将字段的访问权限设为true:即去除private修饰符的影响 field.setAccessible(true); //去除final修饰符的影响,将字段设为可修改的 Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); //把字段值设为200 field.set(null, 200); System.out.println(Bean.INT_VALUE);
100 200
看到测试结果说明咱们的反射修改为功了。测试
class Bean{ public static int nums = 100; }
System.out.println(Bean.nums);
Field field = Bean.class.getField("nums");
field.set(null, 200);
System.out.println(Bean.INT_VALUE);优化
测试结果修改为功。调试
100 200
注意到上述代码的中的静态常量类型是Integer,可是咱们项目中实际须要修改的字段类型并非包装类型Integer,而是java的基本类型int。
当把常量的类型改为int以后。code
class Bean{ private static final int INT_VALUE = 100;//把类型由Integer改为了int }
在其余代码都不变的状况下,代码输出的结果居然变成了诡异的:orm
100 100
并且在调试的过程当中发现,在第二次输出的时候,内存中的Bean.INT_VALUE是已经变成了200,可是System.out.println(Bean.INT_VALUE)输出的结果却依然时诡异的100?!
是反射失效了吗?
又试了其余几种类型,发现这种貌似失效的情会发生在int、long、boolean以及String这些基本类型上,而若是把类型改为Integer、Long、Boolean这种包装类型,或者其余诸如Date、Object都不会出现失效的状况。内存
对于基本类型的静态常量,JAVA在编译的时候就会把代码中对此常量中引用的地方替换成相应常量值。
参考:Modifying final fields in Java
即对于常量 public static final int maxFormatRecordsIndex = 100get
if( index > maxFormatRecordsIndex ){ index = maxFormatRecordsIndex ; }
这段代码在编译的时候已经被java自动优化成这样的:
if( index > 100){
index = 100;
}
因此在INT_VALUE是int类型的时候。编译
System.out.println(Bean.INT_VALUE);
编译时会被优化成下面这样:
System.out.println(100);
因此,天然,不管怎么修改Boolean.INT_VALUE,System.out.println(Bean.INT_VALUE)都仍是会依然执拗地输出100了。
这自己是JVM的优化代码提升运行效率的一个行为,可是就会致使咱们在用反射改变此常量值时出现相似不生效的错觉。class