文档

Java™教程
隐藏目录
获取方法参数的名称
路径: 反射API
课程: 成员
部分: 方法

获取方法参数的名称

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

要将形式参数名称存储在特定的.class文件中,从而使反射API能够检索形式参数名称,请使用javac编译器的-parameters选项编译源文件。

示例MethodParameterSpy演示了如何检索给定类的所有构造函数和方法的形式参数的名称。该示例还打印有关每个参数的其他信息。

以下命令打印类ExampleMethods的构造函数和方法的形式参数名称。 注意:记得使用-parameters编译器选项编译示例ExampleMethods

java MethodParameterSpy ExampleMethods

此命令打印以下内容:

构造函数的数量:1

构造函数 #1
public ExampleMethods()

声明的构造函数数量:1

声明的构造函数 #1
public ExampleMethods()

方法的数量:4

方法 #1
public boolean ExampleMethods.simpleMethod(java.lang.String,int)
             返回类型:boolean
     泛型返回类型:boolean
         参数类型:class java.lang.String
          参数名称:stringParam
               修饰符:0
            是否隐式?:false
        是否存在名称?:true
           是否合成?:false
         参数类型:int
          参数名称:intParam
               修饰符:0
            是否隐式?:false
        是否存在名称?:true
           是否合成?:false

方法 #2
public int ExampleMethods.varArgsMethod(java.lang.String...)
             返回类型:int
     泛型返回类型:int
         参数类型:class [Ljava.lang.String;
          参数名称:manyStrings
               修饰符:0
            是否隐式?:false
        是否存在名称?:true
           是否合成?:false

方法 #3
public boolean ExampleMethods.methodWithList(java.util.List<java.lang.String>)
             返回类型:boolean
     泛型返回类型:boolean
         参数类型:interface java.util.List
          参数名称:listParam
               修饰符:0
            是否隐式?:false
        是否存在名称?:true
           是否合成?:false

方法 #4
public <T> void ExampleMethods.genericMethod(T[],java.util.Collection<T>)
             返回类型:void
     泛型返回类型:void
         参数类型:class [Ljava.lang.Object;
          参数名称:a
               修饰符:0
            是否隐式?:false
        是否存在名称?:true
           是否合成?:false
         参数类型:interface java.util.Collection
          参数名称:c
               修饰符:0
            是否隐式?:false
        是否存在名称?:true
           是否合成?:false

MethodParameterSpy示例使用了Parameter类中的以下方法:

隐式和合成参数

如果某些构造在源代码中没有显式地声明,那么它们会被隐式地声明。例如,ExampleMethods示例中没有包含构造函数。默认构造函数会被隐式地声明。MethodParameterSpy示例会打印关于ExampleMethods的隐式声明构造函数的信息:

声明的构造函数数量: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)
         参数类: class MethodParameterExamples
          参数名称: this$0
               修饰符: 32784
            是否隐式: true
        是否存在名称: true
           是否合成的: false

因为InnerClass的构造函数是隐式声明的,所以它的参数也是隐式的。

注意

Java编译器生成的构造函数被标记为合成的,如果它们不对应于源代码中明确或隐式声明的构造函数,除非它们是类初始化方法。合成的构造函数是由编译器生成的在不同实现之间可能会有所不同的构造函数。考虑下面的示例来自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构造函数的public static字段,这些字段是隐式声明的,而不依赖于它们的构造函数或这些常量的初始化方式。)

因此,示例MethodParameterExample关于enum构造函数Colors的输出如下:

枚举类型 Colors:

构造函数数量:0

已声明的构造函数数量:1

已声明的构造函数 #1
private MethodParameterExamples$Colors()
         参数类:class java.lang.String
         参数名:$enum$name
         修饰符:4096
         是否隐式声明?:false
         名称是否存在?:true
         是否合成的?:true
         参数类:int
         参数名:$enum$ordinal
         修饰符:4096
         是否隐式声明?:false
         名称是否存在?:true
         是否合成的?:true

方法数量:2

方法 #1
public static MethodParameterExamples$Colors[]
    MethodParameterExamples$Colors.values()
         返回类型:class [LMethodParameterExamples$Colors;
         泛型返回类型:class [LMethodParameterExamples$Colors;

方法 #2
public static MethodParameterExamples$Colors
    MethodParameterExamples$Colors.valueOf(java.lang.String)
         返回类型:class MethodParameterExamples$Colors
         泛型返回类型:class MethodParameterExamples$Colors
         参数类:class java.lang.String
         参数名:name
         修饰符:32768
         是否隐式声明?:true
         名称是否存在?:true
         是否合成的?:false

有关隐式声明的构造的更多信息,请参阅Java语言规范,包括在反射API中隐式出现的参数。


上一页: 获取方法类型信息
下一页: 检索和解析方法修饰符