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 部分。
如果没有显式地编写某些构造函数,则在源代码中隐式声明它们。例如,
示例不包含构造函数。默认构造函数是为它隐式声明的。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
的构造函数,所以它的参数也是隐式的。
注意:
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 中显示为隐式的参数。