当前位置: 首页 > 编程笔记 >

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

洪飞龙
2023-03-14
本文向大家介绍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); 

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

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之后。

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 反射如何修改类的常量值、静态变量值、属性值内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!

 类似资料:
  • 主要内容:判定及获取元素的相关方法,值修改相关方法,值可修改条件之一:可被寻址,值可修改条件之一:被导出Go语言中类似 x、x.f[1] 和 *p 形式的表达式都可以表示变量,但是其它如 x + 1 和 f(2) 则不是变量。一个变量就是一个可寻址的内存空间,里面存储了一个值,并且存储的值可以通过内存地址来更新。 对于 reflect.Values 也有类似的区别。有一些 reflect.Values 是可取地址的;其它一些则不可以。考虑以下的声明语句: x := 2 // value type

  • 本文向大家介绍利用反射获取Java类中的静态变量名及变量值的简单实例,包括了利用反射获取Java类中的静态变量名及变量值的简单实例的使用技巧和注意事项,需要的朋友参考一下 JAVA可以通过反射获取成员变量和静态变量的名称,局部变量就不太可能拿到了。 其中要查看的Java类是: 以上这篇利用反射获取Java类中的静态变量名及变量值的简单实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望

  • 本文向大家介绍Java反射如何修改private final成员变量值,包括了Java反射如何修改private final成员变量值的使用技巧和注意事项,需要的朋友参考一下 大家都知道使用java反射可以在运行时动态改变对象的行为,甚至是private final的成员变量,但并不是所有情况下,都可以修改成员变量。今天就举几个小例子说明。 基本数据类型 测试代码: 运行结果:18 此时无法修改成

  • 本文向大家介绍Java反射如何有效的修改final属性值详解,包括了Java反射如何有效的修改final属性值详解的使用技巧和注意事项,需要的朋友参考一下 前言 以前写过一篇 Java 反射修改 final 属性值,本文将在这里重新温习一下Java反射如何有效的修改final属性值,下面话不多说了,来一起看看详细的介绍: 假设有个类 这里声明 name 为非静态的属性只是为了说明反射修改 fina

  • /* main.c */ extern void print_var_1(void); extern void print_var_2(void); int main(void) { print_var_1(); print_var_2(); return 0; } /* static-1.c */ #include <stdio.h> static int var = 1;

  • 本文向大家介绍Java 用反射设置对象的属性值实例详解,包括了Java 用反射设置对象的属性值实例详解的使用技巧和注意事项,需要的朋友参考一下 Java 用反射设置对象的属性值实例详解 Java 反射 创建对象的方法 1、通过Class对象的newInstance()方法,这种方法的局限是只能取调用默认的构造函数 2、通过取得Class对象的getConstructor方法取得Construtor