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


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

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

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

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

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

没有"作弊"是不可能的。

一个技巧可能是编写(或生成(一个类,该类创建一个新的MyClass实例,并使用反射来挖掘出所需的值并将其写入stdout。然后启动一个子JVM来运行该类,并在当前的.中读取它

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

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

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

相关内容

  • 没有找到相关文章

最新更新