获取方法参数的名称

您可以使用方法java.lang.reflect.Executable.getParameters获得任何方法或构造函数的形式参数的名称。 (类MethodConstructor扩展了类Executable,因此继承了方法Executable.getParameters。)但是,.class文件默认情况下不存储形式参数名称。这是因为许多产生和使用类文件的工具可能不会期望包含参数名称的.class文件具有更大的静态和动态覆盖范围。特别是,这些工具将必须处理较大的.class文件,并且 Java 虚拟机(JVM)将使用更多的内存。此外,某些参数名称(例如secretpassword)可能会公开有关安全敏感方法的信息。

要将形式参数名称存储在特定的.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类中的以下方法:

  • getType:返回Class对象,该对象标识参数的声明类型。

  • 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
160x0010形式参数声明为final
40960x1000形式参数是合成的。或者,您可以调用方法isSynthetic
327680x8000该参数在源代码中隐式声明。或者,您可以调用方法isImplicit

隐式和综合参数

如果尚未明确编写某些构造,则会在源代码中隐式声明它们。例如,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)。方法valuesvalueOf被隐式声明。因此,它们的形式参数名称也被隐式声明。

enum构造函数Colors(String name, int ordinal)是默认的构造函数,它是隐式声明的。但是,此构造函数的形式参数(nameordinal)不是隐式声明的。由于这些形式参数均未明确或隐式声明,因此它们是综合的。 (未隐式声明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 中显示为隐式的参数。