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

本文介绍了如何在Java中使用反射来修改一个static final修饰的成员变量的值,详细讲解了代码实现过程,并探讨了可能遇到的问题和解决方案,包括String类型的特殊情况。
摘要由CSDN通过智能技术生成

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

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

代码:

1 /**

2 * 修改静态final字段的值

3 * @author chenzl

4 * 2015-09-22

5 */

6 public classSetFinalValue {

7

8 public static final Map openMap = new HashMap();

9

10 public static void main(String[] args) throwsException {

11 Field target = SetFinalValue.class.getField("openMap");

12

13 int modify =target.getModifiers();

14 SetFinalValue.checkModifier(modify);

15

16 Map openMap2 = new HashMap();

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 openMap3 = new HashMap();

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(intmodify){

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 }

程序结果:

a30bc633aadd47339253381edc68ade0.png

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

图-1:

5387b19b61b8e057e4e09e9230da8639.png

图-2:

eed49ae6b9fe3c20ef29b099c76f68d6.png

图-3:

36bb5e879c9f13bba685c5cb882b965e.png

其他:

1、测试基本数据类型 int

6e0445b44ef85b27ef4d1b97e2dabcbf.png

2、测试Integer类型:

501d80e2e0b736484492b79d98e950cd.png

3、String类型

218cd636bfd03e010a6f574ba0de78ee.png

3.1 String类型的其他方式

db4c25c5787e732425e60d6b9c274ecc.png

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

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

e0b1e507fa3ab23b200f8edcc9d25568.png

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值