不幸的是,您无法做任何您想做的事。 为什么?
在一个我们仍在尝试证明Java并不慢的时代,存储对象的构造位置或方式的元数据会产生很大的开销,并且由于它的使用范围非常小,因此不存在。不仅如此:还有很多技术原因。
原因之一是因为如何实现JVM。Java
class文件格式的规范可以在这里找到。这是一个很大的嘴,但它非常有用。
如前所述,即使在 对象没有名称的 情况下,也可以从任何地方构造 对象
。只有定义为类成员的对象才具有名称(出于访问的明显原因):在方法中构造的对象则没有。JVM具有一个本地变量表,最多包含65535个条目。它们通过
load和 store操作码加载到堆栈中并存储到表中。
换句话说,像
public class Test {int class_member = 42; public Test() { int my_local_field = 42; }}被编译成
public class Test extends java.lang.Object SourceFile: "Test.java" minor version: 0 major version: 50 Constant pool: --snip--{int class_member;public Test(); Code: Stack=2, Locals=2, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: aload_0 5: bipush 42 7: putfield #2; //Field class_member:I 10: bipush 42 12: istore_1 13: return LineNumberTable: --snip-- }在那里,您可以看到一个清晰的示例,
javap -vTest即在
class_member保留名称的同时,将
my_local_field其抽象为局部变量表中的索引1(为保留0
this)。
这本身就给调试器带来了麻烦,因此,设计了一组属性(认为是类文件的元数据)。这些包括LocalVariableTable,LineNumberTable和LocalVariableTypeTable。这些属性对于堆栈跟踪(LineNumberTable)和调试器(LocalVariableTable和LocalVariableTypeTable)很有用。但是,这些是
包含在文件 中的 完全可选的,并且不能保证它们是:
LineNumberTable属性是属性表中的可选可变长度属性
对于其余的人也是如此。
另外,默认情况下,大多数编译器只生成LineNumberTable而不生成任何内容,因此即使有可能,您也会很走运。
基本上,对于开发人员来说,拥有一个
getFieldName(object)(首先对于局部变量是不可能的)是非常令人沮丧的,并且只有当那些属性存在时才起作用。
因此,在可预见的将来,您将无法使用
getFieldStrings。无耻的插件:IntelliJ似乎可以很好地处理反射问题:编写Minecraft
mods我也很了解,可以说IntelliJ大大减少了重构工作。但是对于大多数现代IDE来说,情况可能也是这样:我敢肯定,大型参与者,Eclipse,Netbeans
等。 拥有实施良好的重构系统。



