Java反射:如何获取变量的名称?
使用Java反射,是否可以获取局部变量的名称?例如,如果我有:
Foo b = new Foo();
Foo a = new Foo();
Foo r = new Foo();
是否可以实现一种方法来查找这些变量的名称,如下所示:
public void baz(Foo... foos)
{
for (Foo foo: foos) {
// Print the name of each foo - b, a, and r
System.out.println(***);
}
}
EDIT:这个问题与Is there a way in Java to find the name of the variable that was passed to a function?不同,它更纯粹地询问是否可以使用反射来确定局部变量的名称,而另一个问题(包括公认的答案)更侧重于测试变量的值
# 1 楼答案
这根本不可能。变量名在Java中不通信(并且可能由于编译器优化而被删除)
编辑(与评论相关):
如果您不想将其用作函数参数,这里有一个替代方案(我不会使用它-见下文):
如果
a == b, a == r, or b == r
或存在具有相同引用的其他字段,则会出现问题现在不需要编辑,因为问题已澄清
# 2 楼答案
(编辑:删除之前的两个答案,一个用于回答编辑前的问题,另一个用于回答问题,如果不是绝对错误,至少是接近问题。)
如果使用(
javac -g
)上的调试信息进行编译,则局部变量的名称将保留在中。类文件。例如,以这个简单的类为例:在使用
javac -g:vars TestLocalVarNames.java
编译之后,局部变量的名称现在位于。类文件javap
的-l
标志(“打印行号和局部变量表”)可以显示它们javap -l -c TestLocalVarNames
显示:{a1}解释了我们在这里看到的内容:
§4.7.9 The ^{} Attribute :
LocalVariableTable
存储每个插槽中变量的名称和类型,因此可以将它们与字节码匹配。这就是调试器执行“计算表达式”的方式不过,正如erickson所说,无法通过正常反射访问此表。如果您仍然决心这样做,我相信Java Platform Debugger Architecture (JPDA)会有所帮助(但我自己从未使用过)
# 3 楼答案
从Java8开始,可以通过反射获得一些局部变量名信息。请参阅下面的“更新”部分
完整的信息通常存储在类文件中。一个编译时优化是删除它,节省空间(并提供一些混淆)。但是,当存在时,每个方法都有一个局部变量表属性,该属性列出了局部变量的类型和名称,以及它们所在的指令范围
也许像ASM这样的字节码工程库允许您在运行时检查这些信息。我认为需要这些信息的唯一合理的地方是在开发工具中,因此字节码工程对于其他目的也可能有用
更新:对这个wasadded to Java 8.参数(一个特殊的局部变量类)名称的支持有限,现在可以通过反射获得。除其他目的外,这有助于替换依赖项注入容器使用的
@ParameterName
注释# 4 楼答案
# 5 楼答案
您可以这样做:
# 6 楼答案
您只需创建一个字段数组,然后将其设置为所需的类,如下所示
例如,如果你这样做了
你会得到