【问题标题】:Using reflection to get the initialization value of a field使用反射获取字段的初始化值
【发布时间】:2013-02-08 13:28:39
【问题描述】:
public class MyClass {
    private String s = "foo";
}

是否可以使用反射获得"foo" 而无需实例化新的MyClass

Field field = MyClass.class.getDeclaredField("s");
// -- ideally: --
// Object initializationValue = field.getInitializationValue();
// assert initializationValue.equals("foo");

【问题讨论】:

    标签: java reflection initialization field


    【解决方案1】:

    您所展示的初始化语句实际上已由编译器移入类的构造函数中。您需要实际实例化一个类才能执行它们。当然,这一切都在幕后。但在回答你的问题时,不,你不能,无论如何都不能反思。

    但您可以使用 Soot 等静态分析工具确定这些字段值。

    【讨论】:

      【解决方案2】:

      没有“作弊”是不可能的。

      一种作弊方法可能是编写(或生成)一个类,该类创建一个新的MyClass 实例,并使用反射挖掘出您想要的值并将其写入标准输出。然后你启动一个子 JVM 来运行那个类,并在当前 on 上读取它。

      净结果 - 您在当前 JVM 中没有实例化 MyClass 就获得了值。

      另一个作弊方法是使用字节码库从MyClass“.class”文件中读取字节码,并模拟在当前 JVM 的上下文中执行 MyClass 初始化程序.

      【讨论】:

        【解决方案3】:

        ClassGraph 可以这样做:

        String clsName = "com.xyz.MyClass";
        String s;
        try (ScanResult scanResult =
                new ClassGraph().whitelistClasses(clsName).enableFieldInfo().scan()) {
            s = (String) scanResult.getClassInfo(clsName).getFieldInfo("s")
                    .getConstantInitializerValue();
        }
        

        注意这仅适用于分配给静态最终字段常量初始化器值(可以在没有对象实例化的情况下计算的值,String 除外)。编译器可以在编译时为简单的算术和简单的字符串连接生成一个常量。

        (免责声明,我是ClassGraph的作者)

        如果你不介意加载类,你也可以简单地使用反射来访问静态字段:https://stackoverflow.com/a/4076792/3950982

        【讨论】:

          猜你喜欢
          • 2020-02-13
          • 1970-01-01
          • 2013-01-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-04
          相关资源
          最近更新 更多