栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用Java反射更改私有静态最终字段

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用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";    }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/368996.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号