使用反射获取字段的初始化值

时间:2013-02-08 13:28:39

标签: java reflection initialization field

public class MyClass {
    private String s = "foo";
}

是否可以在不必实例化新"foo"的情况下使用反射MyClass

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

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

没有"作弊"。

一个作弊可能是编写(或生成)一个创建新MyClass实例的类,并使用反射挖掘出你想要的值并将其写入stdout。然后启动子JVM来运行该类,并在当前打开它。

净结果 - 您在没有在当前JVM 中实例化MyClass 的情况下获得了该值。

另一个欺骗是使用字节码库从MyClass" .class"中读取字节码。文件和模拟在当前JVM的上下文中执行MyClass初始化程序。

答案 2 :(得分:0)

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