如何使用Java反射更改私有静态final字段?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (1828)

有一个带有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.TRUEBoolean.FALSE
  • 反射用于更改public static final Boolean.FALSE引用所Boolean引用的Boolean.TRUE
  • 结果,随后每当a false被自动装箱时Boolean.FALSE,它指的是与Boolean所提到的相同Boolean.TRUE
  • "false"现在的一切都是"true"

相关问题

注意事项

每当你做这样的事情时,都应该格外小心。它可能不起作用,因为SecurityManager可能存在,但即使它不存在,取决于使用模式,它可能或可能不起作用。

JLS 17.5.3最终字段的后续修改 在某些情况下,例如反序列化,系统将需要final在构造之后更改对象的字段。final字段可以通过反射和其他依赖于实现的方式来改变。它具有合理语义的唯一模式是构造对象然后final更新对象字段的模式。对象不应该对其他线程可见,也不应该final读取字段,直到final完成对象字段的所有更新。final字段的冻结既发生在final设置字段的构造函数的末尾,也发生在final通过反射或其他特殊机制对字段进行每次修改之后。 即使这样,也有许多并发症。如果final字段在字段声明中初始化为编译时常量,则final可能无法观察到对字段的更改,因为final在编译时将该字段的使用替换为编译时常量。 另一个问题是规范允许积极优化final字段。在一个线程中,允许final使用构造函数中不发生的最终字段的那些修改来重新排序字段的读取。

也可以看看

  • JLS 15.28常量表达式
    • 这种技术不太可能适用于原语private static final boolean,因为它可以作为编译时常量内联,因此“新”值可能无法观察到

附录:关于按位操作

实质上,

field.getModifiers() & ~Modifier.FINAL

关断对应于比特Modifier.FINALfield.getModifiers()&是按位和,并且~是按位补码。

也可以看看

记住常量表达式

仍然无法解决这个问题?,就像我为此所做的那样陷入了萧条?你的代码看起来像这样吗?

public class A {
    private final String myVar = "Some Value";
}

阅读这个答案的评论,特别是@Pshemo的评论,它提醒我,Constant Expression的处理方式不同,因此无法对其进行修改。因此,您需要将代码更改为如下所示:

public class A {
    private final String myVar;

    private A() {
        myVar = "Some Value";
    }
}

热门问答

「九章二号」实现量子计算优越性,未来用量子计算机编程会是怎样的体验?

三掌柜

佰钧成技术有限责任公司 · 架构师 (已认证)

一名合格的、二把刀的、科班的程序猿
量子计算机的概念 量子计算机,简单地说,它是一种可以实现量子计算的机器,是一种通过量子力学规律以实现数学和逻辑运算,处理和储存信息能力的系统。它以量子态为记忆单元和信息储存形式,以量子动力学演化为信息传递与加工基础的量子通讯与量子计算,在量子计算机中其硬件的各种元件的...... 展开详请

程序员过节指南:如何玩转你的1024 ?

三掌柜

佰钧成技术有限责任公司 · 架构师 (已认证)

一名合格的、二把刀的、科班的程序猿
由于1024对于程序员来说,是一个具有特殊意义的数字,运行程序的硬件进制都是以1024为基础的,1G = 1024M,1M = 1024KB,并且1024对程序员来说,是一个非常常用的一个数字,因此从2015年起,有人提议将10.24定为中国的程序员节。 530_82f_6...... 展开详请

程序员过节指南:如何用代码做一个月饼?

YINUXY

腾讯科技有限公司 · 高级架构工程师 (已认证)

一名摸着石头过河的资深小白
推荐
首先来张效果图把: image.png 实现步骤 1、首先我们需要导入画图和数据计算的相关库。 #导入画图和数据计算的相关库 import numpy as np from numpy import sin, cos, pi import matplotlib.pyplot ...... 展开详请

腾讯 99 公益日,技术如何改变公益未来?

在5G时代,会给公益发展趋势带来三个改变:一是公益的广度,传统的公益有了技术的支撑,参与范围会更广;二是基于5G的超快速度,公益会更高效;三是公益的深度会增加,以前做公益、做支援更容易被局限于时空。当然不管技术怎么改变,我们都是想让社会更美好,热爱公益的心和对待社会的温度是不变的...... 展开详请

作为人类高质量程序员,必须掌握哪些算法?

IT小马哥

北京天谱同盛教育科技有限公司 · JAVA高级研发经理 (已认证)

想做个有钱人,却误入程序世界的一个小码农。
推荐
程序 = 数据结构 + 算法 。数据是程序的中心。数据结构和算法两个概念间的逻辑关系贯穿了整个程序世界,首先二者表现为不可分割的关系。没有数据间的有机关系,程序根本无法设计。换言之数据结构是底层,算法就是高层。数据结构为算法提供服务。算法围绕数据结构操作。可以说没有算法的程序是没...... 展开详请

程序员如何维持对编程的热情?

一方面多上github,多实践新的开源项目。思考我能从这些开源项目中学到什么来改进自己的工作。新事物总能给人带来新的乐趣。另一方面定位问题,思考解决方案的过程在未解决问题以前总是无趣的。只有解决的瞬间才有最棒的成就感。长期做自己能力范围外的事容易有挫折感,比如思考数周没有方案的事...... 展开详请

所属标签

扫码关注云+社区

领取腾讯云代金券