获取方法参数的名称
原文: 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: 1
Constructor #1
public ExampleMethods()
Number of declared constructors: 1
Declared constructor #1
public ExampleMethods()
Number of methods: 4
Method #1
public boolean ExampleMethods.simpleMethod(java.lang.String,int)
Return type: boolean
Generic return type: boolean
Parameter class: class java.lang.String
Parameter name: stringParam
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
Parameter class: int
Parameter name: intParam
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
Method #2
public int ExampleMethods.varArgsMethod(java.lang.String...)
Return type: int
Generic return type: int
Parameter class: class [Ljava.lang.String;
Parameter name: manyStrings
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
Method #3
public boolean ExampleMethods.methodWithList(java.util.List<java.lang.String>)
Return type: boolean
Generic return type: boolean
Parameter class: interface java.util.List
Parameter name: listParam
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
Method #4
public <T> void ExampleMethods.genericMethod(T[],java.util.Collection<T>)
Return type: void
Generic return type: void
Parameter class: class [Ljava.lang.Object;
Parameter name: a
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
Parameter class: interface java.util.Collection
Parameter name: c
Modifiers: 0
Is implicit?: false
Is name present?: true
Is synthetic?: false
MethodParameterSpy
示例使用 Parameter
类中的以下方法:
getName
:返回参数的名称。如果参数的名称存在,则此方法返回.class
文件提供的名称。否则,该方法合成形式arg _N_
的名称,其中_N_
是该描述符中的参数的索引。声明参数的方法。例如,假设您编译了类
ExampleMethods
而未指定-parameters
编译器选项。示例MethodParameterSpy
将为方法ExampleMethods.simpleMethod
打印以下内容:public boolean ExampleMethods.simpleMethod(java.lang.String,int)
Return type: boolean
Generic return type: boolean
Parameter class: class java.lang.String
Parameter name: arg0
Modifiers: 0
Is implicit?: false
Is name present?: false
Is synthetic?: false
Parameter class: int
Parameter name: arg1
Modifiers: 0
Is implicit?: false
Is name present?: false
Is 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: 1
public 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 MethodParameterExamples
Parameter name: this$0
Modifiers: 32784
Is implicit?: true
Is name present?: true
Is 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: 0
Number of declared constructors: 1
Declared constructor #1
private MethodParameterExamples$Colors()
Parameter class: class java.lang.String
Parameter name: $enum$name
Modifiers: 4096
Is implicit?: false
Is name present?: true
Is synthetic?: true
Parameter class: int
Parameter name: $enum$ordinal
Modifiers: 4096
Is implicit?: false
Is name present?: true
Is synthetic?: true
Number of methods: 2
Method #1
public static MethodParameterExamples$Colors[]
MethodParameterExamples$Colors.values()
Return type: class [LMethodParameterExamples$Colors;
Generic return type: class [LMethodParameterExamples$Colors;
Method #2
public static MethodParameterExamples$Colors
MethodParameterExamples$Colors.valueOf(java.lang.String)
Return type: class MethodParameterExamples$Colors
Generic return type: class MethodParameterExamples$Colors
Parameter class: class java.lang.String
Parameter name: name
Modifiers: 32768
Is implicit?: true
Is name present?: true
Is synthetic?: false
有关隐式声明的构造的更多信息,请参阅 Java 语言规范,包括在 Reflection API 中显示为隐式的参数。