当前位置: 首页 > 知识库问答 >
问题:

Java反射:如何获取变量的名称?

糜鸿风
2023-03-14

使用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(***); 
    }
}

编辑:这个问题与Java中有没有找到传递给函数的变量名称的方法不同?在这一点上,它更纯粹地询问一个人是否可以使用反射来确定局部变量的名称,而另一个问题(包括公认的答案)更侧重于测试变量的值。

共有3个答案

梁丘高朗
2023-03-14

(编辑:删除了之前的两个答案,一个用于回答编辑前的问题,另一个用于回答问题,如果不是绝对错误,至少是接近问题。)

如果使用(javac-g)上的调试信息进行编译,则局部变量的名称将保留在中。类文件。例如,以这个简单的类为例:

class TestLocalVarNames {
    public String aMethod(int arg) {
        String local1 = "a string";
        StringBuilder local2 = new StringBuilder();
        return local2.append(local1).append(arg).toString();
    }
}

使用javac-g: vars TestLocalVarNames.java编译后,本地变量的名称现在在. class文件中。javap-l标志("打印行号和本地变量表")可以显示它们。

javap-l-c TestLocalVarNames显示:

class TestLocalVarNames extends java.lang.Object{
TestLocalVarNames();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      5      0    this       LTestLocalVarNames;

public java.lang.String aMethod(int);
  Code:
   0:   ldc     #2; //String a string
   2:   astore_2
   3:   new     #3; //class java/lang/StringBuilder
   6:   dup
   7:   invokespecial   #4; //Method java/lang/StringBuilder."<init>":()V
   10:  astore_3
   11:  aload_3
   12:  aload_2
   13:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   16:  iload_1
   17:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   20:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   23:  areturn

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      24      0    this       LTestLocalVarNames;
   0      24      1    arg       I
   3      21      2    local1       Ljava/lang/String;
   11      13      3    local2       Ljava/lang/StringBuilder;
}

VM规范解释了我们在这里看到的内容:

§4.7.9LocalVariableTable属性:

LocalVariableTable属性是code(§4.7.3)属性的可选可变长度属性。调试器可以在方法执行期间使用它来确定给定局部变量的值。

LocalVariableTable存储每个插槽中变量的名称和类型,因此可以将它们与字节码匹配。这就是调试器执行“计算表达式”的方式。

不过,正如埃里克森所说,无法通过正常反射访问此表。如果您仍决心这么做,我相信Java平台调试器体系结构(JPDA)会有所帮助(但我自己从未使用过)。

吴俊晤
2023-03-14

这根本不可能。变量名在Java中不通信(由于编译器优化,也可能被删除)。

编辑(与评论相关):

如果你放弃使用它作为函数参数的想法,这里有一个替代方案(我不会使用——见下文):

public void printFieldNames(Object obj, Foo... foos) {
    List<Foo> fooList = Arrays.asList(foos);
    for(Field field : obj.getClass().getFields()) {
         if(fooList.contains(field.get()) {
              System.out.println(field.getName());
         }
    }
}

如果a==b、a==r或b==r或其他字段具有相同的引用,则会出现问题。

编辑现在没有必要,因为问题得到澄清

洪越泽
2023-03-14

截至Java8,通过反射可以获得一些局部变量名信息。请参见下面的“更新”部分。

完整的信息通常存储在类文件中。编译时优化之一是删除它,节省空间(并提供一些混淆)。然而,当它存在时,每个方法都有一个局部变量表属性,列出局部变量的类型和名称,以及它们在范围内的指令范围。

也许像ASM这样的字节码工程库可以让您在运行时检查这些信息。我认为需要这些信息的唯一合理的地方是在开发工具中,因此字节码工程可能也有其他用途。

更新:Java8中增加了对此的有限支持。参数(局部变量的一个特殊类)名称现在可以通过反射获得。除其他用途外,这有助于替换依赖项注入容器使用的@ParameterName注释。

 类似资料:
  • 问题内容: 使用Java Reflection,是否可以获得本地变量的名称?例如,如果我有这个: 是否有可能实现一种可以找到这些变量名称的方法,如下所示: 问题答案: 从Java 8开始,可以通过反射获得一些局部变量名称信息。请参阅下面的“更新”部分。 完整的信息通常存储在类文件中。一种编译时优化是删除它,节省空间(并提供一些混淆)。但是,如果存在,则每个方法都有一个局部变量表属性,该属性列出了局

  • 有可能得到变量名吗? 例如: 现在打印结果: 屏幕:

  • 我有一个类(在我的项目中是一个单例),带有一些变量。我想通过在函数中传递变量的名称来获得其中的一个变量。现在我有:

  • 本文向大家介绍利用反射获取Java类中的静态变量名及变量值的简单实例,包括了利用反射获取Java类中的静态变量名及变量值的简单实例的使用技巧和注意事项,需要的朋友参考一下 JAVA可以通过反射获取成员变量和静态变量的名称,局部变量就不太可能拿到了。 其中要查看的Java类是: 以上这篇利用反射获取Java类中的静态变量名及变量值的简单实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望

  • 如何获取到实体类的变量名,用的tkmybatis,没有方法引用,现在写的条件都是字符串"isDeleted"这种,不好维护,有没有方式Dog.的方式拿到变量名称,不想写好多常量,有没有类似Lombok注解的方式去实现

  • 可能重复: Java反射:如何获取变量的名称? 我发现关于这个话题的讨论很多,但从来没有令人满意的答案。。 我怎样才能得到变量的名称并得到字符串作为结果?这在Java可能吗?