public class MyClass {
private String s = "foo";
}
是否可以在不必实例化新"foo"
的情况下使用反射MyClass
?
Field field = MyClass.class.getDeclaredField("s");
// -- ideally: --
// Object initializationValue = field.getInitializationValue();
// assert initializationValue.equals("foo");
答案 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