获取方法参数的名称
原文: https://docs.oracle.com/javase/tutorial/reflect/member/methodparameterreflection.html
您可以使用方法 java.lang.reflect.Executable.getParameters 获取任何方法或构造器的形式参数的名称。 (类 Method 和 Constructor 扩展类 Executable ,因此继承了Executable.getParameters方法。)但是,.class文件默认情况下不存储形式参数名称。这是因为许多生成和使用类文件的工具可能不会期望包含参数名称的.class文件的较大静态和动态占用空间。特别是,这些工具必须处理更大的.class文件,而 Java 虚拟机(JVM)将使用更多的内存。此外,某些参数名称(如secret或password)可能会公开有关安全敏感方法的信息。
要将正式参数名称存储在特定的.class文件中,从而使 Reflection API 能够检索形式参数名称,请使用-parameters选项将源文件编译为javac编译器。
MethodParameterSpy 示例说明了如何检索给定类的所有构造器和方法的形式参数的名称。该示例还打印有关每个参数的其他信息。
以下命令打印类 ExampleMethods的构造器和方法的形式参数名称。 注意:记得使用-parameters编译器选项编译示例ExampleMethods:
java MethodParameterSpy ExampleMethods
此命令打印以下内容:
Number of constructors: 1Constructor #1public ExampleMethods()Number of declared constructors: 1Declared constructor #1public ExampleMethods()Number of methods: 4Method #1public boolean ExampleMethods.simpleMethod(java.lang.String,int)Return type: booleanGeneric return type: booleanParameter class: class java.lang.StringParameter name: stringParamModifiers: 0Is implicit?: falseIs name present?: trueIs synthetic?: falseParameter class: intParameter name: intParamModifiers: 0Is implicit?: falseIs name present?: trueIs synthetic?: falseMethod #2public int ExampleMethods.varArgsMethod(java.lang.String...)Return type: intGeneric return type: intParameter class: class [Ljava.lang.String;Parameter name: manyStringsModifiers: 0Is implicit?: falseIs name present?: trueIs synthetic?: falseMethod #3public boolean ExampleMethods.methodWithList(java.util.List<java.lang.String>)Return type: booleanGeneric return type: booleanParameter class: interface java.util.ListParameter name: listParamModifiers: 0Is implicit?: falseIs name present?: trueIs synthetic?: falseMethod #4public <T> void ExampleMethods.genericMethod(T[],java.util.Collection<T>)Return type: voidGeneric return type: voidParameter class: class [Ljava.lang.Object;Parameter name: aModifiers: 0Is implicit?: falseIs name present?: trueIs synthetic?: falseParameter class: interface java.util.CollectionParameter name: cModifiers: 0Is implicit?: falseIs name present?: trueIs synthetic?: false
MethodParameterSpy示例使用 Parameter 类中的以下方法:
getName:返回参数的名称。如果参数的名称存在,则此方法返回.class文件提供的名称。否则,该方法合成形式arg _N_的名称,其中_N_是该描述符中的参数的索引。声明参数的方法。例如,假设您编译了类
ExampleMethods而未指定-parameters编译器选项。示例MethodParameterSpy将为方法ExampleMethods.simpleMethod打印以下内容:public boolean ExampleMethods.simpleMethod(java.lang.String,int)Return type: booleanGeneric return type: booleanParameter class: class java.lang.StringParameter name: arg0Modifiers: 0Is implicit?: falseIs name present?: falseIs synthetic?: falseParameter class: intParameter name: arg1Modifiers: 0Is implicit?: falseIs name present?: falseIs synthetic?: false
getModifiers:返回一个整数,表示形式参数拥有的各种特征。如果适用于形式参数,则此值是以下值的总和:| 值(十进制) | 值(十六进制 | 描述 | | —- | —- | —- | | 16 | 0×0010 | 形式参数声明为
final| | 4096 | 为 0x1000 | 形式参数是合成的。或者,您可以调用方法isSynthetic。 | | 32768 | 为 0x8000 | 该参数在源代码中隐式声明。或者,您可以调用方法isImplicit|isImplicit:如果在源代码中隐式声明此参数,则返回true。有关详细信息,请参阅隐式和合成参数部分。isNamePresent:如果参数根据.class文件具有名称,则返回true。isSynthetic:如果在源代码中既未隐式声明也未显式声明此参数,则返回true。有关详细信息,请参阅隐式和合成参数部分。
如果未明确编写某些构造,则会在源代码中隐式声明这些构造。例如, ExampleMethods示例不包含构造器。默认构造器是为它隐式声明的。 MethodParameterSpy示例打印有关ExampleMethods的隐式声明构造器的信息:
Number of declared constructors: 1public ExampleMethods()
请考虑 MethodParameterExamples的以下摘录:
public class MethodParameterExamples {public class InnerClass { }}
类InnerClass是非静态嵌套类或内部类。内部类的构造器也是隐式声明的。但是,此构造器将包含一个参数。当 Java 编译器编译InnerClass时,它会创建一个代表类似于以下代码的.class文件:
public class MethodParameterExamples {public class InnerClass {final MethodParameterExamples parent;InnerClass(final MethodParameterExamples this$0) {parent = this$0;}}}
InnerClass构造器包含一个参数,其类型是包含InnerClass的类,即MethodParameterExamples。因此,示例MethodParameterExamples打印以下内容:
public MethodParameterExamples$InnerClass(MethodParameterExamples)Parameter class: class MethodParameterExamplesParameter name: this$0Modifiers: 32784Is implicit?: trueIs name present?: trueIs synthetic?: false
因为隐式声明了类InnerClass的构造器,所以它的参数也是隐式的。
注:
- Java 编译器为内部类的构造器创建形式参数,以使编译器能够将创建表达式中的引用(表示直接封闭的实例)传递给成员类的构造器。
- 值 32784 表示
InnerClass构造器的参数既是 final(16),也是隐式(32768)。 - Java 编程语言允许带有美元符号的变量名称(
$);但是,按照惯例,美元符号不会用于变量名称。
如果 Java 编译器发出的构造与源代码中显式或隐式声明的构造不对应,则将其标记为 synthetic ,除非它们是类初始化方法。合成构造是由编译器生成的工件,这些工件在不同的实现之间变化。考虑以下 MethodParameterExamples的摘录:
public class MethodParameterExamples {enum Colors {RED, WHITE;}}
当 Java 编译器遇到enum构造时,它会创建几个与.class文件结构兼容的方法,并提供enum构造的预期功能。例如,Java 编译器将为enum构造Colors创建一个.class文件,该文件表示类似于以下内容的代码:
final class Colors extends java.lang.Enum {public final static Colors RED = new Colors("RED", 0);public final static Colors BLUE = new Colors("WHITE", 1);private final static values = new Colors[]{ RED, BLUE };private Colors(String name, int ordinal) {super(name, ordinal);}public static Colors[] values(){return values;}public static Colors valueOf(String name){return (Colors)java.lang.Enum.valueOf(Colors.class, name);}}
Java 编译器为此enum构造创建三个构造器和方法:Colors(String name, int ordinal),Colors[] values()和Colors valueOf(String name)。方法values和valueOf是隐式声明的。因此,它们的形式参数名也被隐式声明。
enum构造器Colors(String name, int ordinal)是默认构造器,它是隐式声明的。但是,此构造器的形式参数(name和ordinal)是而不是隐式声明的。由于这些形式参数既未明确声明也未隐式声明,因此它们是合成的。 (enum构造的默认构造器的形式参数不是隐式声明的,因为不同的编译器不需要在这个构造器的形式上达成一致;另一个 Java 编译器可能为它指定不同的形式参数。当编译器编译使用[COD5 的表达式]时]常量,它们仅依赖于enum构造的公共静态字段,这些字段是隐式声明的,而不是它们的构造器或这些常量的初始化方式。)
因此,示例MethodParameterExample打印有关enum构造Colors的以下内容:
enum Colors:Number of constructors: 0Number of declared constructors: 1Declared constructor #1private MethodParameterExamples$Colors()Parameter class: class java.lang.StringParameter name: $enum$nameModifiers: 4096Is implicit?: falseIs name present?: trueIs synthetic?: trueParameter class: intParameter name: $enum$ordinalModifiers: 4096Is implicit?: falseIs name present?: trueIs synthetic?: trueNumber of methods: 2Method #1public static MethodParameterExamples$Colors[]MethodParameterExamples$Colors.values()Return type: class [LMethodParameterExamples$Colors;Generic return type: class [LMethodParameterExamples$Colors;Method #2public static MethodParameterExamples$ColorsMethodParameterExamples$Colors.valueOf(java.lang.String)Return type: class MethodParameterExamples$ColorsGeneric return type: class MethodParameterExamples$ColorsParameter class: class java.lang.StringParameter name: nameModifiers: 32768Is implicit?: trueIs name present?: trueIs synthetic?: false
有关隐式声明的构造的更多信息,请参阅 Java 语言规范,包括在 Reflection API 中显示为隐式的参数。
