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