我有一堂课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"
。
实际执行的操作如下:
boolean
值true
和false
in自动main
装箱以引用类型Boolean
“常量”,Boolean.TRUE
并且Boolean.FALSE
public static final Boolean.FALSE
引用Boolean
的Boolean.TRUE
false
被自动装箱到时Boolean.FALSE
,它所指的含义与所指的相同Boolean
。Boolean.TRUE
"false"
现在的一切都是"true"
static final File.separatorChar
单元测试Integer
的缓存,使a发生突变String
等每当您这样做时,都应格外小心。它可能不起作用,因为SecurityManager
可能存在a,但是即使它不存在,根据使用方式的不同,它可能也可能不起作用。
在某些情况下,例如反序列化,系统将需要
final
在构造后更改对象的字段。final
字段可以通过反射和其他依赖于实现的方式进行更改。具有合理语义的唯一模式是构造一个对象,然后final
更新该对象的字段的模式。在完成对对象字段的final
所有更新之前,不应使该对象对其他线程可见,也不应读取final
字段。final
字段冻结发生在final
设置该字段的构造函数的末尾,以及在final
通过反射或其他特殊机制对字段进行每次修改之后立即冻结。即使那样,仍然存在许多并发症。如果
final
在字段声明中将字段初始化为编译时常量,则final
可能不会观察到对该字段的更改,因为final
在编译时会将该字段的使用替换为编译时常量。另一个问题是,该规范允许对
final
字段进行积极的优化。在一个线程内,允许对final
字段的读取进行重新排序,而对最终字段的修改不会在构造函数中发生。
private static final boolean
函数一起使用,因为它作为编译时常量是可内联的,因此“ new”值可能无法观察到本质上,
field.getModifiers() & ~Modifier.FINAL
关闭与Modifier.FINAL
from 相对应的位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] 删除。
我来说两句