使用反射设置私有静态最终字段 [英] Setting private static final field with reflection

查看:56
本文介绍了使用反射设置私有静态最终字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于使用Java反射更改私有静态final字段,我试图设置一个私有的静态最终字段.

Based on Change private static final field using Java reflection, I tried to set a private static final field.

(我知道这非常骇人听闻,但这个问题与代码质量无关;它与 Java 反射有关.)

(I know this is terribly hacky, but this question is not about code quality; it's about Java reflection.)

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 上试过了.

I've tried this with OpenJDK 6 and 7, and Oracle 7.

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

I don't know what guarantees Java reflection gives. But if it failed, I thought there would be an Exception (practically all the reflection methods throw exceptions).

这里发生了什么?

推荐答案

Java 内联 final 字段 初始化为 编译时常量表达式.

Java inlines final fields that are initialized to constant expressions at compile time.

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

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并返回它.

Decompile the bytecode and you'll find that the body of getA() simply pushes the constant 1 and returns it.

* - JavaWorld 引用说 static final.Kumar 指出 语言规范常量变量的定义中.我认为 Kumar 是对的,而 JavaWorld 是错误的.

* - The JavaWorld quote says static final. Kumar points out that the static is not required by the language specification in the definition of a constant variable. I think Kumar is right and JavaWorld is in error.

这篇关于使用反射设置私有静态最终字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆