Java 反射修改类的常量值、静态变量值、属性值实例详解

在本篇文章里小编给大家整理的是一篇关于Java 反射修改类的常量值、静态变量值、属性值实例详解内容,有兴趣的读者们可以跟着学习下。

前言

有的时候,我们需要修改一个变量的值,但变量也许存在于 Jar 包中或其他位置,导致我们不能从代码层面进行修改,于是我们就用到了下面的场景,通过反射来进行修改变量的值。

定义一个实体类

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

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

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

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

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);测试结果修改成功。100200

奇怪的地方

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

当把常量的类型改成int之后。

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

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

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 = 100

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的优化代码提高运行效率的一个行为,但是就会导致我们在用反射改变此常量值时出现类似不生效的错觉。

到此这篇关于Java 反射修改类的常量值、静态变量值、属性值实例详解的文章就介绍到这了,更多相关Java 反射如何修改类的常量值、静态变量值、属性内容搜索编程之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程之家!

相关文章

Java中的String是不可变对象 在面向对象及函数编程语言中,不...
String, StringBuffer 和 StringBuilder 可变性 String不可变...
序列化:把对象转换为字节序列的过程称为对象的序列化. 反序...
先说结论,是对象!可以继续往下看 数组是不是对象 什么是对...
为什么浮点数 float 或 double 运算的时候会有精度丢失的风险...
面试题引入 这里引申出一个经典问题,看下面代码 Integer a ...