假设没有
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
在里面
main
自动装箱到引用类型
Boolean
“常量”
Boolean.TRUE
和
Boolean.FALSE
因此,随后
假
是自动装箱的
假错误
,它指的是相同的
布尔
正如所指
布尔真
以前的一切
"false"
现在是
"true"
相关问题
告诫
每当你做这种事时,都要格外小心。它可能不起作用,因为
安全管理器
可能存在,但即使不存在,根据使用模式的不同,它也可能工作,也可能不工作。
在某些情况下,如反序列化,系统将需要更改
最终的
构造后的对象字段。
最终的
字段可以通过反射和其他依赖于实现的方法进行更改。唯一具有合理语义的模式是构造一个对象,然后
最终的
对象的字段将被更新。对象不应对其他线程可见,也不应
最终的
在所有更新到
最终的
对象字段已完成。冻结
最终的
字段同时出现在构造函数的末尾,其中
最终的
设置字段,并在每次修改
最终的
通过反射或其他特殊机制的场。
即便如此,也有许多并发症。如果A
最终的
字段在字段声明中初始化为编译时常量,更改为
最终的
不可能观测到磁场,因为它的使用
最终的
字段在编译时替换为编译时常量。
另一个问题是,规范允许对
最终的
领域。在线程内,允许对
最终的
对最后一个字段所做的那些修改不会在构造函数中发生的字段。
也见
JLS 15.28 Constant Expression
这种技术不太可能与原始的
private static final boolean
,因为它是作为编译时间常数的inlineable,因此“new”值可能不可观测。
附录:关于位操作
基本上,
field.getModifiers() & ~Modifier.FINAL
关闭对应于
Modifier.FINAL
从
field.getModifiers()
.
&
是位与,和
~
是位补码。
也见
记住常量表达式
还是不能解决这个问题?像我一样陷入抑郁?您的代码看起来像这样吗?
public class A {
private final String myVar = "Some Value";
}
读到关于这个答案的评论,特别是@pshemo的评论,它提醒我
Constant Expressions
处理方式不同,所以
不可能的
修改它。因此,您需要将代码更改为如下所示:
public class A {
private final String myVar;
private A() {
myVar = "Some Value";
}
}
如果你不是班级的主人…我感觉到你了!
有关此行为的原因的详细信息
read this
?