利用反射对修饰符为final的成员变量进行修改
来源:互联网 发布:淘宝5星好评评语 编辑:程序博客网 时间:2024/05/14 09:00
假设我们有如下一个类,我们要利用反射来对其成员变量就行修改:
class Entity { public int i = 1;}
一般我们会这么做:
try { Entity e = new Entity(); System.out.println("before: " + e.i); Field f = Entity.class.getDeclaredField("i"); f.setInt(e, 2); // 或者这样 //f.set(e, 2);// java会自动装箱拆箱 System.out.println("after: " + e.i);} catch (Exception e) { e.printStackTrace();}
结果输出:
before: 1after: 2
但是如果我们的成员变量是final呢?
class Entity { public final int i = 1;}
我们再用上面的方式来进行修改值,发现出异常了:
java.lang.IllegalAccessException: Can not set final int field com.test.Entity.i to (int)2
那我们该怎么办呢?我们可以修改成员变量的final修饰符,使其变为public int i = 1;具体方法如下:
try { Entity e = new Entity(); System.out.println("before: " + e.i); Field f = Entity.class.getDeclaredField("i"); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); // 输出17:表示修饰符为:public final System.out.println(f.getModifiers()); /* 这里就是要修改修饰符了,至于为什么是f.getModifiers() & ~Modifier.FINAL,大家看一下Modifier的源码就知道了*/ modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); // 输出1:表示修饰符已经被修改为:public System.out.println(f.getModifiers()); f.setAccessible(true); f.setInt(e, 2); //f.set(e, 3); System.out.println("after: " + e.i);} catch (Exception e) { e.printStackTrace();}
没有抛出异常了,但是确没有出现我们想要的结果,输出为:
before: 1171after: 1
这是为什么呢?我们稍微修改下Entity的代码如下:
class Entity { public final Integer i = 1;}
然后再执行,发现结果已经被修改了:
before: 1171after: 3
说明我可以对对象数据类型进行修改,而不能对基本数据类型进行修改
我们再来试试String类型的:
class Entity { public final String s = "a";}
try { Entity e = new Entity(); System.out.println("before: " + e.s); Field f = Entity.class.getDeclaredField("s"); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); System.out.println(f.getModifiers()); modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); System.out.println(f.getModifiers()); f.setAccessible(true); //f.setInt(e, 2); f.set(e, "b"); System.out.println("after: " + e.s);} catch (Exception e) { e.printStackTrace();}
结果输出:
before: a171after: a
咦?竟然木有改变?
我们再对Entity稍微改动下:
class Entity { public final String s = new String("a");}
结果输出:
before: a171after: b
修改成功,至于为什么会这样,那得问java虚拟机了
好了,总结一下,对于final修改的成员变量,基本数据以及public final String s = "a";这种方式不可被修改
而对于对象数据类型是可以突破final限制进行修改的,但是一般我们也很少会这么用
0 0
- 利用反射对修饰符为final的成员变量进行修改
- 通过反射修改 被 private final static修饰的成员
- 关于成员变量中final修饰符的使用说明
- final 修饰的成员变量无默认值!
- final修饰的成员变量初始化时机
- 利用反射机制操作私有成员变量(private修饰的变量)
- 对被final修饰的变量进行赋值的几种方法
- 【java】对被final修饰的变量进行赋值的几种方法
- java final修饰成员变量赋值的二种方法
- final修饰的变量
- 利用反射技术修改类中的字段(成员变量的反射)
- final修饰符---final变量
- 对const volatile修饰符共同修改变量的解释
- 成员变量修饰符
- 利用反射将字段为String类型的成员变量中的字符串中的i改为Q
- Java final修饰的变量
- final修饰变量的问题
- 被static修饰的成员变量可以被修改吗
- spark读写hdfs后出现的异常错误
- LightOJ 1294:Positive Negative Sign
- Jsp之二 tomcat安装配置使用
- 图像处理PSNR及其计算(OpenCV和matlab实现)
- Java 常用排序算法/程序员必须掌握的 8大排序算法
- 利用反射对修饰符为final的成员变量进行修改
- 一些方法
- 集合中contains方法体会
- 关于Ubuntu 64位系统的32位兼容库问题
- 小鱼人的华丽变身-皮肤模型替换
- php+linux的crontab实现定时抓取csdn文章到mysql数据库
- 小马哥----高仿苹果6sp主板型号A9910-尾插盖板A992标示 刷机拆机图与开机界面图
- Java高级之虚拟机垃圾回收机制
- hdu2073无限的路