Java Reflection: How to get the name of a variable?

后端 未结 8 2378
一生所求
一生所求 2020-11-22 00:28

Using Java Reflection, is it possible to get the name of a local variable? For example, if I have this:

Foo b = new Foo();
Foo a = new Foo();
Foo r = new Fo         


        
8条回答
  •  心在旅途
    2020-11-22 01:31

    (Edit: two previous answers removed, one for answering the question as it stood before edits and one for being, if not absolutely wrong, at least close to it.)

    If you compile with debug information on (javac -g), the names of local variables are kept in the .class file. For example, take this simple class:

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

    After compiling with javac -g:vars TestLocalVarNames.java, the names of local variables are now in the .class file. javap's -l flag ("Print line number and local variable tables") can show them.

    javap -l -c TestLocalVarNames shows:

    class TestLocalVarNames extends java.lang.Object{
    TestLocalVarNames();
      Code:
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."":()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."":()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;
    }
    

    The VM spec explains what we're seeing here:

    §4.7.9 The LocalVariableTable Attribute:

    The LocalVariableTable attribute is an optional variable-length attribute of a Code (§4.7.3) attribute. It may be used by debuggers to determine the value of a given local variable during the execution of a method.

    The LocalVariableTable stores the names and types of the variables in each slot, so it is possible to match them up with the bytecode. This is how debuggers can do "Evaluate expression".

    As erickson said, though, there's no way to access this table through normal reflection. If you're still determined to do this, I believe the Java Platform Debugger Architecture (JPDA) will help (but I've never used it myself).

提交回复
热议问题