2016-07-29 87 views
2

可以通过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"

+0

号变量名的它仅仅是那里的程序员的方便;编译器将它们抛出。 –

+0

考虑一下你认为应该为printLocalVariables(1,one + 1)打印的内容。 –

+0

但是,您可以获取内存位置表示。所以,“one”可以变成@ 2123d517,你可以来回追踪这个“指针”。如果它在这种情况下具有相同的值,那么它是相同的变量。例如, – Bonatti

回答

2

理论上有可能。

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

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

1

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

1

在你的例子中onetwo将在呼叫站点内联,并且在编译的代码中没有留下踪迹。 UPS。

如果你想要的是简单的日志记录,并且使用的是InteliJ(你应该!),然后使用代码模板。他们允许使用本地名称,因此您将输入one.log<tab>并获得one.log("one"),例如

1

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

是,编程变得局部变量名在一定条件下是可能的。

  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); 
       } 
     } 
    } 
} 
  • 我不知道这一点,但我想,你也可以做一个使用LocalVariable类的Java调试接口
  • 相关问题