使用reflection设置私有静态最终字段
基于使用Javareflection更改私有静态最终字段 ,我尝试设置私有静态最终字段。
(我知道这非常hacky,但这个问题不是关于代码质量;而是关于Javareflection。)
import java.lang.reflect.Field; import java.lang.reflect.Modifier; class Main { static class Foo { private static final int A = 1; int getA() { return A; } } public static void main(String[] args) throws Exception { Field modifiers = Field.class.getDeclaredField("modifiers"); modifiers.setAccessible(true); Field field = Foo.class.getDeclaredField("A"); field.setAccessible(true); modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(null, 2); System.out.println(new Foo().getA()); // should print 2 } }
这打印
1
我用OpenJDK 6和7以及Oracle 7试过这个。
我不知道Javareflection给出了什么保证。 但是如果它失败了,我认为会有一个Exception
(几乎所有的reflection方法都抛出exception)。
这里发生了什么?
Java内联在编译时初始化为常量表达式的 final
字段 。
根据Java语言规范,任何使用可在编译时计算的表达式初始化的
static final
*字段必须编译为“内联”字段值的字节代码。 也就是说,Main
类中不会出现动态链接,告诉它在运行时从InterfaceA
获取A
的值。
反编译字节码,你会发现getA()
的主体只是推动常量1
并返回它。
* – JavaWorld引用static final
。 Kumar指出,在常量变量的定义中, 语言规范并不要求static
。 我认为Kumar是对的,JavaWorld是错误的。