我如何获取这些方法参数名称?
基本上,您需要:
- 获取对 a 的引用
Class
- 来自
Class
,获取对a的引用Method
通过致电getDeclaredMethod() or getDeclaredMethods()
它返回对的引用Method
objects
- 来自
Method
对象、调用(从 Java 8 开始新增)getParameters()
它返回一个数组Parameter
objects
- On the
Parameter
对象、调用getName()
Class<String> clz = String.class;
for (Method m : clz.getDeclaredMethods()) {
System.err.println(m.getName());
for (Parameter p : m.getParameters()) {
System.err.println(" " + p.getName());
}
}
Output:
...
indexOf
arg0
indexOf
arg0
arg1
...
据我所知,.class 文件不存储形式参数。那么我如何使用反射来获取它们呢?
请参阅 javadocParameter.getName():
... 如果参数的名称存在,那么这个方法返回类文件提供的名称. 否则,这个方法合成 argN 形式的名称,其中 N 是声明参数的方法的描述符中参数的索引。
JDK 是否支持此功能是特定于实现的(正如您从上面的输出中看到的,JDK 8 的 build 125 不支持它)。类文件格式支持可选属性,这些属性可由特定 JVM/javac 实现使用,并且会被不支持它的其他实现忽略。
请注意,您甚至可以使用以下命令生成上述输出arg0
, arg1
, ...对于 Java 8 之前的 JVM - 您需要知道的只是可通过以下方式访问的参数计数Method.getParameterTypes()
:
Class<String> clz = String.class;
for (Method m : clz.getDeclaredMethods()) {
System.err.println(m.getName());
int paramCount = m.getParameterTypes().length;
for (int i = 0; i < paramCount; i++) {
System.err.println(" arg" + i);
}
}
JDK 8 的新增功能是有一个扩展的 API 和可能性为 JVM 提供真实参数名称代替arg0
, arg1
, ...
支持此类可选功能可以通过可选属性它可以附加到各种类文件结构。看4.6.方法为了method_info
类文件中的结构。也可以看看4.7.1.定义和命名新属性在 JVM 规范中。
由于在 JDK 8 中,类文件版本将增加到 52,因此也可以更改文件格式本身来支持此功能。
也可以看看JEP 118:在运行时访问参数名称了解更多信息和实施替代方案。建议的实现模型是添加一个存储参数名称的可选属性。由于类文件格式已经支持这些可选属性,因此在某种程度上这甚至是可能的,以便旧版 JVM 仍然可以使用类文件,而按照规范的要求,它们会被简单地忽略:
Java 虚拟机实现需要默默地忽略它们无法识别的属性。
Update
正如 @assylias 所建议的,源代码需要使用以下命令进行编译javac
命令行选项-parameters
为了将参数名称反射的元数据添加到类文件中。但是,这当然只会影响使用此选项编译的代码 - 上面的代码仍然会打印arg0
, arg1
等等,因为运行时库不是使用此标志编译的,因此类文件中不包含必要的条目。