如何使用反射在Java 8中获取方法参数名称? [英] How to get Method Parameter names in Java 8 using reflection?

查看:259
本文介绍了如何使用反射在Java 8中获取方法参数名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java 8能够使用Reflection API获取方法参数名称。

Java 8 has the ability to acquire method parameter names using Reflection API.


  1. 如何获取这些方法参数名称?

  1. How can I get these method parameter names?

据我所知,类文件不存储正式的参数名称。如何使用反射获得这些?

As per my knowledge, class files do not store formal parameter names. How can I get these using reflection?


推荐答案


我如何获得这些方法参数名称(一些示例代码)?

基本上,你需要至:

  • get a reference to a Class
  • From the Class, get a reference to a Method by calling getDeclaredMethod() or getDeclaredMethods() which returns references to Method objects
  • From the Method object, call (new as of Java 8) getParameters() which returns an array of Parameter objects
  • On the Parameter object, call 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());
   }
}

输出:

...
indexOf
  arg0
indexOf
  arg0
  arg1
...








另外根据我的知识.class文件不存储形式参数。然后我如何使用反射得到它们?

请参阅javadoc以获取 参数。 getName()

See the javadoc for Parameter.getName():


... 如果参数的名称存在,然后此方法返回类文件提供的名称否则,此方法合成argN 形式的名称,其中N是声明参数的方法的描述符中参数的索引。

... If the parameter's name is present, then this method returns the name provided by the class file. Otherwise, this method synthesizes a name of the form argN, where N is the index of the parameter in the descriptor of the method which declares the parameter.

JDK是否支持此功能,是特定于实现的(正如您在上面的输出中看到的那样,JDK 8的build 125不支持它)。类文件格式支持可选属性,这些属性可由特定JVM / javac实现使用,并且被不支持它的其他实现忽略。

Whether a JDK supports this, is implementation specific (as you can see form the above output, build 125 of JDK 8 does not support it). The class file format supports optional attributes which can be used by a specific JVM/javac implementation and which are ignored by other implementations which do not support it.

请注意,您甚至可以使用 arg0 arg1 ,...使用Java 8之前的JVM - 您需要知道的是参数计数,可以通过 Method.getParameterTypes()访问:

Note that you could even generate the above output with arg0, arg1, ... with pre Java 8 JVMs - all you need to know is the parameter count which is accessible through 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 ,...

What is new with JDK 8 is that there is an extended API and the possibility for JVMs to provide the real parameter names instead of arg0, arg1, ...

通过可选属性可以支持这些可选功能,可以附加到各种类文件结构。请参见 4.6。方法用于类文件中的 method_info 结构。另请参见 4.7.1。在JVM规范中定义和命名新属性

Supporting such optional features is possible through optional attributes which can be attached to the various class file structures. See 4.6. Methods for the method_info structure within a class file. See also 4.7.1. Defining and Naming New Attributes in the JVM spec.

由于使用JDK 8,类文件版本将增加到52,因此也可以更改文件格式本身以支持此功能。

Since with JDK 8, the class file version will be incremented to 52, it would also be possible to change the file format itself to support this feature.

另请参阅 JEP 118:访问运行时参数名称以获取更多信息和实施备选方案。建议的实现模型是添加一个存储参数名称的可选属性。由于类文件格式已经支持这些可选属性,因此甚至可以通过某种方式实现类文件,以便较旧的JVM仍然可以使用它们,它们根据规范的要求被忽略:

See also JEP 118: Access to Parameter Names at Runtime for more information and implementation alternatives. The proposed implementation model is to add an optional attribute which stores the parameter names. Since the class file format already supports these optional attributes, this would even be possible in a way so that the class files can still be used by older JVMs, where they are simply ignored as demanded by the spec:


需要Java虚拟机实现静默忽略它们无法识别的属性。

Java Virtual Machine implementations are required to silently ignore attributes they do not recognize.

更新

根据@assylias的建议,源代码需要使用 javac 命令行选项 -parameters ,以便将参数名称反射的元数据添加到类文件中。但是,这当然只会影响使用此选项编译的代码 - 上面的代码仍将打印 arg0 arg1 等因为运行时库不是用这个标志编译的,因此不包含类文件中的必要条目。

As suggested by @assylias, the source needs to be compiled with the javac command line option -parameters in order to add the meta data for parameter name reflection to the class file. However, this will of course only affect code compiled with this option - the code above will still print arg0, arg1 etc. since the runtime libraries are not be compiled with this flag and hence do not contain the necessary entries in the class files.

这篇关于如何使用反射在Java 8中获取方法参数名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆