获取方法参数的名称
您可以使用方法java.lang.reflect.Executable.getParameters获得任何方法或构造函数的形式参数的名称。 (类Method和Constructor扩展了类Executable,因此继承了方法Executable.getParameters
。)但是,.class
文件默认情况下不存储形式参数名称。这是因为许多产生和使用类文件的工具可能不会期望包含参数名称的.class
文件具有更大的静态和动态覆盖范围。特别是,这些工具将必须处理较大的.class
文件,并且 Java 虚拟机(JVM)将使用更多的内存。此外,某些参数名称(例如secret
或password
)可能会公开有关安全敏感方法的信息。
要将形式参数名称存储在特定的.class
文件中,从而使 Reflection API 能够检索形式参数名称,请使用javac
编译器的-parameters
选项编译源文件。
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
文件提供的名称。否则,此方法将合成格式为argN
的名称,其中N
是在声明该参数的方法的 Descriptors 中该参数的索引。
例如,假设您在编译类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:返回一个整数,表示形式参数具有的各种 Feature。该值是以下值的总和(如果适用于形式参数):
值(十进制) | 值(十六进制) | Description |
---|---|---|
16 | 0x0010 | 形式参数声明为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
是非静态的nested class或内部类别。内部类的构造函数也被隐式声明。但是,此构造函数将包含一个参数。 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
的构造函数是隐式声明的,所以其参数也是隐式的。
Note :
-
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<Colors> {
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 编译器可能为其指定了不同的形式参数.当编译器编译使用enum
常量的表达式时,它们会仅依赖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 中显示为隐式的参数。