使用反射设置私有静态最终字段

时间:2014-08-20 14:41:15

标签: java reflection

基于Change private static final field using Java reflection,我尝试设置私有静态最终字段。

(我知道这非常hacky,但这个问题不是关于代码质量;而是关于Java反射。)

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。

我不知道Java反射给出了什么。但是如果它失败了,我认为会有Exception(几乎所有的反射方法都抛出异常)。

这里发生了什么?

1 个答案:

答案 0 :(得分:9)

在编译时初始化为inlines final fields的Java constant expressions

  

根据Java语言规范,任何使用可在编译时计算的表达式初始化的static final * 字段必须编译为“内联”字段值的字节代码。也就是说,类Main内不会出现动态链接,告诉它在运行时从A获取InterfaceA的值。

反编译字节码,你会发现getA()的主体只是推动常量1并返回它。


* - JavaWorld引用static final。 Kumar指出language specification常量变量的定义中不需要static。我认为Kumar是对的,JavaWorld是错误的。