java - 使用反射设置私有(private)静态最终字段

标签 java reflection

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

(我知道这非常 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(实际上所有的反射方法都会抛出异常)。

这里发生了什么?

最佳答案

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

According to the Java Language Specification, any static final* field initialized with an expression that can be evaluated at compile time must be compiled to byte code that "inlines" the field value. That is, no dynamic link will be present inside class Main telling it to obtain the value for A from InterfaceA at runtime.

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


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

关于java - 使用反射设置私有(private)静态最终字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25407656/

相关文章:

c# - 反射和装箱值类型

Java - 找不到逻辑错误

java.lang.IllegalStateException : Could not locate PropertySource and the fail fast property is set, 微服务失败

java - 使用匹配的正则表达式调用子类的方法

java - 了解 Java 反射的缺点

c# - 为什么相互比较 2 个 .NET 框架类会导致 stackoverflow 异常?

java - GET 请求失败,JAX-RS : Could not find MessageBodyWriter for response object of type: java. util.ArrayList 媒体类型:text/html

java - Java SecretKeySpec 的 C# 等价物是什么

java - Proguard:保留特定方法的注释

scala - TypeRef 和 Type 有什么区别?