[Java] 如何保存方法中参数的名称

75 阅读2分钟

如何保存方法中参数的名称

结论

方法的参数名称可以保存在 MethodParameters 属性中。

代码验证

Java

请将以下代码保存为 A.java ⬇️

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

class A {
    int add(int p1, int p2) {
        return p1 + p2;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = A.class.getDeclaredMethod("add", int.class, int.class);
        for (Parameter parameter : method.getParameters()) {
            System.out.println(parameter.getName());
        }
    }
}

用如下命令可以编译 A.java 并运行其中的 main(...) 方法 ⬇️

javac A.java
java A

运行结果如下 ⬇️

arg0
arg1

java.lang.reflect.Parameter#getNamejavadoc 可以看到,arg0/arg1 都是合成的名称。

image.png

为了保存参数的名称,我们需要在使用 javac 命令时使用 -parameters 选项。 让我们用如下的命令再运行一次 ⬇️

javac -parameters A.java
java A

结果如下

p1
p2

那么参数的名称是如何保存的呢?我们可以用以下的命令来查看 A.class 的内容 ⬇️

javap -v -p A

完整的结果有点长,我只把与 add(int, int) 方法相关的部分展示出来 ⬇️

int add(int, int);
    descriptor: (II)I
    flags: (0x0000)
    Code:
      stack=2, locals=3, args_size=3
         0: iload_1
         1: iload_2
         2: iadd
         3: ireturn
      LineNumberTable:
        line 6: 0
    MethodParameters:
      Name                           Flags
      p1
      p2

看来参数名 (就这个例子而言,是 p1/p2) 保存在了 MethodParameters 属性里。 Java Virtual Machine Specification 4.7.24. The MethodParameters Attribute 中有关于这个属性的详细描述。

Scala

在使用 Scala 时,我们也可以保存和读取参数的名称。让我们用代码来验证吧 (请将以下代码保存为 B.scala)

class B {
  def add(p1: Int, p2: Int): Int = {
    p1 + p2
  }
}

下方的命令可以编译 B.scala

scalac B.scala

我们用下方的命令可以看到对应字节码的详细内容

javap -v -p B

完整的结果有点长,我只把和 add 方法相关的部分粘贴过来

public int add(int, int);
    descriptor: (II)I
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=3
         0: iload_1
         1: iload_2
         2: iadd
         3: ireturn
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       4     0  this   LB;
            0       4     1    p1   I
            0       4     2    p2   I
    MethodParameters:
      Name                           Flags
      p1                             final
      p2                             final

看来 Scala 也会使用 MethodParameters 属性来保存参数的名称。

参考资料