可以在Java或Kotlin中以编程方式获取局部变量名称吗?

时间:2016-07-29 16:19:00

标签: 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转换为字符串"one"

4 个答案:

答案 0 :(得分:2)

理论上,它是可能的。

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

但请注意,此属性是可选的。编译器可以省略添加此调试信息。

答案 1 :(得分:1)

不,这是不可能的。只传递变量值,没有可以提供名称的数据。

答案 2 :(得分:1)

如果您的示例onetwo将在调用网站中内联,并且在编译的代码中不留下任何痕迹。窗口。

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

答案 3 :(得分:1)

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

是的,在某些情况下可以通过编程方式获取本地变量名称。

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

  2. 来获取这些代码。
  3. 如果您使用调试信息编译了.class文件,则可以从中读取本地变量,例如使用asm的ClassReader。 以下代码查看了A类函数f1

  4. 的局部变量

    以下是代码:

    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 Debug Interface的LocalVariable类来实现它。