java反射 面试题_使用Java反射更改私有静态最终字段

假设没有SecurityManager阻止你执行此操作,则可以使用setAccessible来绕开private并重置修饰符以摆脱final,并实际上修改private static final字段。

这是一个例子:

import java.lang.reflect.*;

public class EverythingIsTrue {

static void setFinalStatic(Field field, Object newValue) throws Exception {

field.setAccessible(true);

Field modifiersField = Field.class.getDeclaredField("modifiers");

modifiersField.setAccessible(true);

modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

field.set(null, newValue);

}

public static void main(String args[]) throws Exception {

setFinalStatic(Boolean.class.getField("FALSE"), true);

System.out.format("Everything is %s", false); // "Everything is true"

}

}

假设没有SecurityException抛出,上面的代码将打印出来”Everything is true”。

实际执行的操作如下:

基本boolean值true和falsein自动main装箱以引用类型Boolean“常量”,Boolean.TRUE并且Boolean.FALSE

反射用于更改所public static final Boolean.FALSE引用Boolean的Boolean.TRUE

结果,随后每当a false被自动装箱到时Boolean.FALSE,它所指的含义与所指的相同Boolean。Boolean.TRUE

“false”现在的一切都是”true”

相关问题

使用反射更改static final File.separatorChar单元测试

如何将setAccessible限制为仅“合法”使用?

有实例弄乱Integer的缓存,使a发生突变String等

注意事项

每当你执行此类操作时,都应格外小心。它可能不起作用,因为SecurityManager可能存在a,但是即使它不存在,根据使用方式的不同,它可能也可能不起作用。

JLS 17.5.3随后对最终字段的修改

在某些情况下,例如反序列化,系统将需要final在构造后更改对象的字段。final可以通过反射和其他依赖实现的方式来更改字段。具有合理语义的唯一模式是构造一个对象,然后final更新该对象的字段的模式。在完成对对象字段的final所有更新之前,不应使该对象对其他线程可见,也不应读取final字段。final字段冻结发生在final设置该字段的构造函数的末尾,以及在final通过反射或其他特殊机制对字段进行每次修改之后立即冻结。

即使那样,仍然存在许多并发症。如果final在字段声明中将字段初始化为编译时常量,则final可能不会观察到对该字段的更改,因为final在编译时会将该字段的使用替换为编译时常量。

另一个问题是规范允许对final字段进行积极的优化。在一个线程内,允许对final字段的读取进行重新排序,而对最终字段的修改不会在构造函数中发生。

也可以看看

JLS 15.28常数表达式

这项技术不太可能与原始private static final boolean函数一起使用,因为它可以作为编译时常量内联,因此“ new”值可能无法观察到

附录:关于按位操作

实质上,

field.getModifiers() & ~Modifier.FINAL

关闭与Modifier.FINALfrom 相对应的位field.getModifiers()。&是按位与,并且~是按位补码。

也可以看看

维基百科/按位操作

记住常数表达式

仍然无法解决这个问题吗?像我一样,陷入了抑郁吗?你的代码看起来像这样吗?

public class A {

private final String myVar = "Some Value";

}

阅读关于该答案的注释,特别是@Pshemo的注释,它使我想起了常量表达式的处理方式不同,因此将无法对其进行修改。因此,你需要将代码更改为如下所示:

public class A {

private final String myVar;

private A() {

myVar = "Some Value";

}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值