1. 程式人生 > >java1.8獲取類和介面函式引數名稱

java1.8獲取類和介面函式引數名稱

程式碼如下

package js.oop.parameter;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;

/**
 * java 1.8
 * 編譯器時加上-parameters
 */
public abstract class ParameterName {

    public void fun(String name1,int age1) {
        System.out.println("name:" + name1 + ",age:" + String.valueOf(age1));
    }

    public abstract void test(String msg,int age);

    /**
     * 切換編譯環境 java1.8
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws  Exception {
        Method method = ParameterName.class.getMethod("fun",String.class,int.class);
        //@since 1.8
        Parameter[] parameters= method.getParameters();
        Arrays.stream(parameters).forEach(parameter -> {
             System.out.println(parameter.getName());
        });

        method = ParameterName.class.getMethod("test",String.class,int.class);
        parameters= method.getParameters();
        Arrays.stream(parameters).forEach(parameter -> {
            System.out.println(parameter.getName());
        });
    }

}

  預設情況下:獲取的結果是 arg0 和 arg1 ,為什麼呢?檢視 parameter.getName() 的原始碼如下:

 public String getName() {
        // Note: empty strings as paramete names are now outlawed.
        // The .equals("") is for compatibility with current JVM
        // behavior.  It may be removed at some point.
        if(name == null || name.equals(""))
            return "arg" + index;
        else
            return name;
    }

那麼怎麼才能通過程式碼獲取引數名稱呢? 

編譯器時加上-parameters引數

方式1:idea配置編譯時引數:

方式2:maven外掛配置編譯時引數

編譯後檢視class位元組碼檔案

javap -v ParameterName.class >> 123.txt

發現有不一樣的地方.class檔案中額外儲存引數的元資訊 MethodParameters

public void fun(java.lang.String, int);
    descriptor: (Ljava/lang/String;I)V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=3, args_size=3
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: new           #3                  // class java/lang/StringBuilder
         6: dup
         7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        10: ldc           #5                  // String name:
        12: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        15: aload_1
        16: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        19: ldc           #7                  // String ,age:
        21: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        24: iload_2
        25: invokestatic  #8                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;
        28: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        31: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        34: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        37: return
      LineNumberTable:
        line 14: 0
        line 15: 37
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      38     0  this   Ljs/oop/parameter/ParameterName;
            0      38     1 name1   Ljava/lang/String;
            0      38     2  age1   I
    MethodParameters:
      Name                           Flags
      name1
      age1

  public abstract void test(java.lang.String, int);
    descriptor: (Ljava/lang/String;I)V
    flags: ACC_PUBLIC, ACC_ABSTRACT
    MethodParameters:
      Name                           Flags
      msg
      age