Java reflection modifies the constant value, static variable value and attribute value of a class

preface

Sometimes, we need to modify the value of a variable, but the variable may exist in the jar package or other locations, so we can't modify it from the code level, so we use the following scenario to modify the value of the variable through reflection.

Define an entity class

class Bean{  
    private static final Integer INT_VALUE = 100;  
}  
@H_404_9@

利用反射修改私有静态常量方法

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);  
@H_404_9@

修改私有静态常量测试结果

100
200
@H_404_9@

看到测试结果说明我们的反射修改成功了。

利用反射修改共有静态变量方法

class Bean{  
    public static int nums = 100;
}  
@H_404_9@
@H_404_9@

System.out.println(Bean.nums);
Field field = Bean.class.getField("nums");
field.set(null,200);
System.out.println(Bean.INT_VALUE);

@H_404_9@

测试结果修改成功。

100
200
@H_404_9@

奇怪的地方

注意到上述代码的中的静态常量类型是Integer,但是我们项目中实际需要修改的字段类型并不是包装类型Integer,而是java的基本类型int。
当把常量的类型改成int之后。

class Bean{  
    private static final int INT_VALUE = 100;//把类型由Integer改成了int  
}
@H_404_9@

在其他代码都不变的情况下,代码输出的结果竟然变成了诡异的:

100
100
@H_404_9@

而且在调试的过程中发现,在第二次输出的时候,内存中的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 = 100

if( index > maxFormatRecordsIndex   ){  
    index  =  maxFormatRecordsIndex ;  
}  
@H_404_9@

这段代码在编译的时候已经被java自动优化成这样的:
if( index > 100){
index = 100;
}
所以在INT_VALUE是int类型的时候。

System.out.println(Bean.INT_VALUE);  
@H_404_9@

编译时会被优化成下面这样:
System.out.println(100);
所以,自然,无论怎么修改Boolean.INT_VALUE,System.out.println(Bean.INT_VALUE)都还是会依然固执地输出100了。
这本身是JVM的优化代码提高运行效率的一个行为,但是就会导致我们在用反射改变此常量值时出现类似不生效的错觉。

总结

以上是编程之家为你收集整理的Java 反射修改类的常量值、静态变量值、属性值全部内容,希望文章能够帮你解决Java 反射修改类的常量值、静态变量值、属性值所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
喜欢与人分享编程技术与工作经验,欢迎加入编程之家官方交流群!
编程之家官方1群
编程之家官方2群
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>