Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
你可以使用方法 java.lang.reflect.Executable.getParameters 获取任何方法或构造函数的形式参数的名称。(类 Method 和 Constructor 继承类 Executable 因此继承方法 Executable.getParameters。)但是,.class 文件默认不存储形式参数名。这是因为许多生成和使用类文件的工具可能不会期望包含参数名称的 .class 文件的较大静态和动态占用空间。特别是,这些工具必须处理较大的 .class 文件,Java 虚拟机(JVM)将使用更多内存。此外,某些参数名称(如 secret 或 password)可能会公开有关安全性敏感方法的信息。
要将形式参数名称存储在特定的 .class 文件中,从而使反射 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 文件提供的名称。否则,此方法合成一个名称 argN,其中 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 | 0x0010 | 形式参数声明为 final |
| 4096 | 0x1000 | 形式参数是合成的。或者,你可以调用方法 isSynthetic。 |
| 32768 | 0x8000 | 该参数在源代码中隐式声明。或者,你可以调用方法 isImplicit |
isImplicit:如果在源代码中隐式声明此参数,则返回 true。有关详细信息,请参阅 Implicit and Synthetic Parameters 部分。
isNamePresent:如果参数根据 .class 文件具有名称,则返回 true。
isSynthetic:如果在源代码中既没有隐式声明也没有显式声明此参数,则返回 true。有关详细信息,请参阅 Implicit and Synthetic Parameters 部分。
如果没有显式地编写某些构造函数,则在源代码中隐式声明它们。例如, 示例不包含构造函数。默认构造函数是为它隐式声明的。ExampleMethodsMethodParameterSpy 示例打印有关 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 的构造函数,所以它的参数也是隐式的。
注意:
InnerClass 构造函数的参数既是 final(16),也是隐式(32768)。$);但是,按照规范,美元符号不会用于变量名称。如果 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 Language Specification,包括在反射 API 中显示为隐式的参数。