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

fixitagain:

我有一堂课private static final,但不幸的是,我需要在运行时更改它。

使用反射我得到这个错误: java.lang.IllegalAccessException: Can not set static final boolean field

有什么办法可以改变价值?

Field hack = WarpTransform2D.class.getDeclaredField("USE_HACK");
hack.setAccessible(true);
hack.set(null, true);
多基因润滑剂:

假设没有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"

实际执行的操作如下:

  • 基本booleantruefalsein自动main装箱以引用类型Boolean“常量”,Boolean.TRUE并且Boolean.FALSE
  • 反射用于更改所public static final Boolean.FALSE引用BooleanBoolean.TRUE
  • 结果,随后每当a false被自动装箱到时Boolean.FALSE,它所指的含义与所指的相同BooleanBoolean.TRUE
  • "false"现在的一切都是"true"

相关问题


注意事项

每当您这样做时,都应格外小心。它可能不起作用,因为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";
    }
}

如果您不是课程的所有者,我会感觉到您!

有关为什么此行为的更多详细信息,请阅读此内容

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

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

Java反射,更改私有静态最终字段没有做任何事情

无法使用Java反射更改静态最终字段?

用反射设置私有静态最终字段

私有静态最终字段

使用反射设置私有字段适用于静态或最终版本,但不适用于静态最终版本(组合)

使用Mockito或Jmockit模拟私有静态最终字段

使用弹簧注入分配私有静态最终字段成员

Java反射设置静态最终字段失败

私有静态字段不是最终的吗?

如何使用反射(Java)调用私有静态方法?

使用Spock在Java中模拟私有静态最终变量

使用Java反射获取Scala特性中的私有字段

关于字段的私有静态最终关键字的快速Java问题

最终和私有静态

您可以使用反射更改DateTime对象中_dateData的私有字段值吗?

Java中“私有静态最终”和“公共静态最终”类变量的最接近Ruby表示?

Java反射获取所有私有字段

删除ctor后,无法通过反射设置私有最终字段

如何使用Java中的反射确定字段是私有的还是受保护的?

Eclipse在静态方法之前对私有静态最终字段进行排序

java - 在构造函数中使用反射设置最终字段

Java:通过反射(行为)访问私有字段

Java反射嵌套对象设置私有字段

为什么允许通过反射访问Java私有字段?

在Java中通过反射获取私有字段

通过Java中的反射访问私有继承的字段

Java模拟私有最终字段或响应表单RestHighLevelClient

使用反射访问 golang 中包的私有字段