[英]Cannot change static final field using java reflection?
I recently stumbled upon Change private static final field using Java reflection and tested polygenelubricants' EverythingIsTrue
class, works fine, System.out.format("Everything is %s", false);
我最近偶然发现了使用Java反射的Change private static final字段,并测试了polygenelubricants的EverythingIsTrue
类,可以正常工作, System.out.format("Everything is %s", false);
prints Everything is true
indeed. 打印Everything is true
。 But when I change the code as 但是当我将代码更改为
public class EverythingIsTrue {
public static final boolean FALSE = false;
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(EverythingIsTrue.class.getField("FALSE"), true);
System.out.format("Everything is %s", FALSE);
}
}
it prints 它打印
Everything is false
Does anybody know why? 有人知道为什么吗? Does setFinalStatic actually work or not? setFinalStatic是否实际起作用?
You can avoid compiler inlining by making the value a result of a method call, even a dummy one. 通过使值成为方法调用的结果(甚至是虚拟调用),可以避免编译器内联。
public class Main {
// value is not known at compile time, so not inlined
public static final boolean FLAG = Boolean.parseBoolean("false");
static void setFinalStatic(Class clazz, String fieldName, Object newValue) throws NoSuchFieldException, IllegalAccessException {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
Field modifiers = field.getClass().getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
public static void main(String... args) throws Exception {
System.out.printf("Everything is %s%n", FLAG);
setFinalStatic(Main.class, "FLAG", true);
System.out.printf("Everything is %s%n", FLAG);
}
}
prints 版画
Everything is false
Everything is true
When accessing primitive static final fields, the Java compiler will assume that the value is a constant and inline the value instead of generating code that accesses the field. 当访问原始静态final字段时,Java编译器将假定该值是一个常量,并内联该值,而不是生成访问该字段的代码。 This means that the compiler will replace with the reference to the FALSE
field with the value false
. 这意味着编译器将使用值为false
对FALSE
字段的引用替换。 If you use reflection to access the field, you will see that the value of the field has actually changed. 如果使用反射来访问该字段,您将看到该字段的值实际上已更改。
This will not work for non-primitive fields, as the value of an object reference can not be inlined at compile time. 这不适用于非基本字段,因为在编译时无法内联对象引用的值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.