反射修改private static final修饰的属性

问题

反射到底能否修改被private static final修饰的属性?按常规反射获取属性,然后赋值,会发生什么?

代码

反射要修改的属性是Test2.NUMBER

public class Test2 {

    private static final Integer NUMBER = 1;

    public static Integer getNumber() {
        return NUMBER;
}

测试方法

@Test
public void test() throws Exception {
     Field number = Test2.class.getDeclaredField("NUMBER");
     Test2 o = Test2.class.newInstance();
     number.setAccessible(true);
     number.set(o, 3);
     System.out.println(Test2.getNumber());
}     

我们期望输出的是3,而结果会抛出如下异常:
异常
网上查了很多例子,关于String的这里不再追述,关于int或Integer的,也基本都是说不能用反射赋值。
但是真的就不行了吗,是不能用反射,还是不能这样用反射呢?

结果

正好我最近发现hugegraph新版代码中有这个问题,于是提了issue,维护人员刚刚回复他们会去核实代码中是否存在此问题,并且告诉我如果要使用源码,可以先参考这个链接解决上述问题
stackoverflow解决此问题的地址
方法如下,参数1,要赋值的属性,参数2,新值

private static void setFinalStatic(Field field, Object newValue) throws NoSuchFieldException, IllegalAccessException {
	field.setAccessible(true);
	Field modifiersField = Field.class.getDeclaredField("modifiers");
	modifiersField.setAccessible(true);
	modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
	field.set(null, newValue);
}

原demo中用的是Boolean,将false成功改成了true,我这里还是使用上述的Integer,测试方法如下

@Test
public void test() throws Exception {
    Field number = Test2.class.getDeclaredField("NUMBER");
 	setFinalStatic(number, 3);
    System.out.println(Test2.getNumber());
}

神奇的事情发生了,Test2.NUMBER原值是1,这里输出了3
3
于是我尝试将Test2中的NUMBER修改为int,看看如果不是包装类型,还能否修改,结果如下:
1
看来这种方法对包装类型的private static final可以进行修改了,但对于基本类型,虽然不会抛出之前的异常了,但仍然无法成功赋值。
对于这种方法的原理还没有理解,还是不太建议在生产环境中使用这样的代码。当然了,生产环境自己写的代码,大概率也不会想去写成private static final再去反射修改。如果是必须要对引入的第三方jar中的属性做修改,或许可以尝试尝试。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值