首页 > 编程语言 > 详细

JAVA 利用反射修改修饰符为static+final的成员变量的值

时间:2015-09-24 15:58:51      阅读:1555      评论:0      收藏:0      [点我收藏+]

问题:今天项目有一个需求,需要new一个HashMap,将它赋值给一个修饰符为static+final的Map。

思路:不能停服,那就只能动态修改了,那必然用到反射。反射的一些基础知识请自行学习

参考:1、http://my.oschina.net/dxqr/blog/215504?p={{totalPage}} 

     2、http://stackoverflow.com/questions/3301635/change-private-static-final-field-using-java-reflection

代码:

 1 /**
 2  * 修改静态final字段的值
 3  * @author chenzl
 4  * 2015-09-22
 5  */
 6 public class SetFinalValue {
 7 
 8     public static final Map<Integer, Integer> openMap = new HashMap<Integer, Integer>();
 9     
10     public static void main(String[] args) throws Exception {
11         Field target = SetFinalValue.class.getField("openMap");
12         
13         int modify = target.getModifiers();
14         SetFinalValue.checkModifier(modify);
15         
16         Map<Integer, Object> openMap2 = new HashMap<Integer, Object>();
17         openMap2.put(2, "abcde");
18         try {
19             //取消 Java 语言访问检查,详细查看 API(这里可以不写)
20             target.setAccessible(true);
21             
22             //获得修饰符Field对象,通过这个对象可以对另外一个Field对象的操作符进行修改,源码见图-1
23             Field modifiersField = Field.class.getDeclaredField("modifiers");
24             modifiersField.setAccessible(true);
25             
26             //关于Modefier常量的定义见图-2
27             modify = target.getModifiers() & ~Modifier.FINAL;
28             System.out.println("处理后的 modify : " + modify);
29             
30             //更改目标对象的修饰符
31             modifiersField.setInt(target, modify);
32             modify = target.getModifiers();
33             
34             System.out.println("#####更改修饰符后的结果######");
35             SetFinalValue.checkModifier(modify);
36             
37             //更改静态常量
38             target.set(null, openMap2);
39             
40             System.out.println(openMap.get(2));
41         } catch (Exception e) {
42             e.printStackTrace();
43         }
44         
45         /**重复设置一次*/
46         Map<Integer, Object> openMap3 = new HashMap<Integer, Object>();
47         openMap3.put(3, "中文输入");
48         try {
49             target = SetFinalValue.class.getField("openMap");
50             target.setAccessible(true);
51             System.out.println("#####重复一次检验一次重新get后值会不会改变######");
52             checkModifier(target.getModifiers());
53             
54         } catch (Exception e) {
55             e.printStackTrace();
56         }
57         
58     }
59     
60     /**
61      * 检查所有的修饰符,是否是 public static final
62      * @param modify
63      */
64     public static void checkModifier(int modify){
65         System.out.println("当前的 modify : " + modify);
66         //源码见图-3
67         System.out.println(" public : " + Modifier.isPublic(modify));
68         System.out.println(" static : " + Modifier.isStatic(modify));
69         System.out.println(" final : " + Modifier.isFinal(modify));
70     }
71 }

 

程序结果:

技术分享

总结:先拿到成员变量的Field对象,从Field对象中获得所有修饰符,修改它的修饰符,然后设置对象的值。

 

 

图-1:

技术分享 

图-2:

技术分享

 图-3:

技术分享

 

 

其他:

1、测试基本数据类型 int

技术分享

 

2、测试Integer类型:

技术分享

 

3、String类型

技术分享

3.1 String类型的其他方式

技术分享

 

关于String类型出现的特殊情况,我暂时也不知道原因,猜测是与String类型的常量池有关,有待我以后去证实。

当我用一个新的常量去替换时成功了。

技术分享

那么我暂时理解成 open变量指向常量池的一个内存地址,在编译器就确定了,不能动态指向常量池外的内存地址,只能重新指向常量池内的另外一个内存地址。

 

 

 

技术分享
技术分享

JAVA 利用反射修改修饰符为static+final的成员变量的值

原文:http://www.cnblogs.com/chenzl1024/p/4835319.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!