在Java或Kotlin中以编程方式获取本地变量名称是可能的?

在Java或Kotlin中以编程方式获取本地变量名称是可能的?

例如,这个代码

public void printOneTwo() { int one = 1; int two = 2; printLocalVariables(one, two); } private void printLocalVariables(Objects... variables) { //code } //result: "one, two" 

我需要将变量转换为字符串"one"

理论上,这是可能的。

您可以使用像ASM这样的字节代码解析器从声明类的类文件中提取方法的局部变量表。 这个表格包含了所有局部变量的名字以及它们有效性的偏移量来标识声明顺序。

不过请注意,这个属性是可选的。 编译器可以省略添加这个调试信息。

不,这是不可能的。 只有变量值被传递,没有可以给你名字的数据可用。

在你的例子中, onetwo在呼叫站点中将被内联,并且在编译的代码中不会留下任何踪迹。 UPS。

如果你想要的只是简单的日志记录,而且你正在使用InteliJ(你应该!),那么就使用代码模板。 它们允许使用本地名称,因此,您将输入one.log<tab>并获取one.log("one") ,例如

这是个有趣的问题。 但是目的是什么? 这只是一个练习?

是的,在某些条件下可以通过编程获取局部变量名称。

  1. 根据一些定义,在java中,函数参数是一种局部变量。 如果代码是使用调试信息编译的,则可以使用java反射,method.getParameterTypes()

  2. 如果你有一个用调试信息编译的.class文件,你可以从中读取它的局部变量,例如使用asm的ClassReader。 以下代码查看A类函数f1的本地语言

这里是代码:

 import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.LocalVariableNode; import org.objectweb.asm.tree.MethodNode; public class Example { public static void main(String[] args) throws FileNotFoundException, IOException { ClassReader reader = new ClassReader(new FileInputStream(new File("A.class"))); final ClassNode classNode = new ClassNode(); reader.accept((ClassVisitor) classNode, 0); for (final MethodNode mn : (List<MethodNode>)classNode.methods) { if ( mn.name.equals("f1")) for (LocalVariableNode n : (List<LocalVariableNode>)mn.localVariables) { System.out.println(n.name); } } } } 
  1. 我不确定这一点,但我认为你也可以使用Java调试接口的LocalVariable类