使用Java Reflection,是否可以获得局部变量的名称?例如,如果我有:
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?的不同之处在于,它更纯粹地询问是否可以使用反射来确定局部变量的名称,而另一个问题(包括可接受的答案)更侧重于测试变量的值。*
8条答案
按热度按时间ut6juiuv1#
从Java 8开始,一些局部变量名信息可以通过反射获得。请参见下面的“更新”部分。
完整的信息通常存储在类文件中。一个编译时优化是将其删除,以节省空间(并提供一些混淆)。然而,当它存在时,每个方法都有一个局部变量表属性,列出局部变量的类型和名称,以及它们在作用域中的指令范围。
也许像ASM这样的字节码工程库可以让你在运行时检查这些信息,我能想到的需要这些信息的唯一合理的地方是在开发工具中,所以字节码工程也可能对其他目的有用。
@ParameterName
注解。r6l8ljro2#
这是完全不可能的。变量名在Java中是不能通信的(也可能由于编译器优化而被删除)。
编辑(与注解相关):
如果你放弃把它作为函数参数的想法,这里有一个替代方案(我不会使用它--见下文):
如果
a == b, a == r, or b == r
或其他字段具有相同的引用,则会出现问题。由于问题已澄清,现在无需编辑
ctzwtxfj3#
(* 编辑:删除之前的两个答案,一个是在编辑之前回答的问题,另一个是,如果不是绝对错误,至少接近它。*)
如果使用(
javac -g
)上的调试信息进行编译,则局部变量的名称将保留在.class文件中。例如,以下面的简单类为例:使用
javac -g:vars TestLocalVarNames.java
编译后,局部变量的名称现在位于.class文件中。javap
的-l
标志(“打印行号和局部变量表”)可以显示它们。javap -l -c TestLocalVarNames
显示:VM spec解释了我们在这里看到的情况:
§4.7.9
LocalVariableTable
属性:LocalVariableTable
属性是Code
(§4.7.3)属性的一个可选的变长属性,它可以被调试器用来在方法执行期间确定给定局部变量的值。LocalVariableTable
在每个槽中存储变量的名称和类型,因此可以将它们与字节码匹配。这就是调试器如何执行“Evaluate expression”的方法。正如erickson所说,虽然没有办法通过正常的反射来访问这个表,但是如果你仍然决心要这么做,我相信Java Platform Debugger Architecture (JPDA)会有所帮助(但是我自己从来没有用过)。
trnvg8h34#
7uhlpewt5#
你可以这样做:
o2rvlv0m6#
您需要做的就是创建一个字段数组,然后将其设置为您想要的类,如下所示。
比如说如果你
你会得到
klsxnrf17#
更新@Marcel Jackwerth对一般问题的回答。
并且只使用类属性,不使用方法变量。
6tdlim6h8#
请参见以下示例: