`
QING____
  • 浏览: 2234150 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA反射获取方法参数名

    博客分类:
  • JAVA
 
阅读更多

    默认情况下,我们是无法获取方法中参数的名称,通过反射机制也只能过去参数的顺序以及一些表意名:arg0、arg1等等;当我们面对,比如文档化服务接口的详细信息时,就会比较麻烦。因为源文件在编译时,不会将参数名称等相关meta信息记入class文件;JDK 8之后,我们可以通过在编译时指定“-parameters”选项,来实现将方法的参数名记入class文件,并在运行时通过反射机制获取相关信息。

 

    如果你的项目为maven构建,可以增加如下配置:

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <encoding>utf8</encoding>
        <compilerArgs>
            <arg>-parameters</arg>
        </compilerArgs>
    </configuration>
</plugin>

  

    普通JAVA与反射机制:

public class Test {

    public static void main(String[] args) throws Exception{
        Class clazz = Class.forName("com.test.MethodParameterTest");
        Method[] methods = clazz.getMethods();
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("+++" + constructor.getName());
            Parameter[] parameters = constructor.getParameters();
            for (Parameter parameter : parameters) {
                printParameter(parameter);
            }
        }

        System.out.println("------------------");
        for (Method method : methods) {
            System.out.println(method.getName());
            Parameter[] parameters = method.getParameters();
            for (Parameter parameter : parameters) {
                printParameter(parameter);
            }
        }
    }

    private static void printParameter(Parameter parameter) {
        //参数名
        System.out.println("\t\t" + parameter.getName());
        //是否在源码中隐式声明的参数名
        System.out.println("\t\t\t implicit:" + parameter.isImplicit());
        //类文件中,是否存在参数名
        System.out.println("\t\t\t namePresent:" + parameter.isNamePresent());
        //是否为虚构参数
        System.out.println("\t\t\t synthetic:" + parameter.isSynthetic());
        System.out.println("\t\t\t VarArgs:" + parameter.isVarArgs());
    }
}

 

    Spring环境下:

public class SpringTest {

    private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();


    public static void main(String[] args) throws Exception{

        Class clazz = Class.forName("com.test.MethodParameterTest");
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
            //JDK 1.8 + is better.
            String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
            if (parameterNames == null) {
                continue;
            }
            for (String pn : parameterNames) {
                System.out.println("\t\t" + pn);
            }
        }
    }
}

 

    1、isImplicit(): 参数是否为“隐式”声明在源文件中,比如内部类,默认构造函数(无参)其实在编译成class时将会把包含它的主类引用作为首个参数,此参数即为隐式声明;如果为true,即表示有JDK编译器隐式生成在class文件中的方法参数,而source文件中并不可见。常规的普通的方法,此值为false。

 

    2、isNamePresent:此参数在class文件中是否有此参数名;受制于在编译时是否指定了“-parameter”,对于指定此参数的编译文件,通常为true;对于JDK 内部类、默认编译的类,通常为false;此时你会发现,它们的参数名通常为表意名称:arg0、arg1等等,此时为false。

 

    3、isSynthetic():是否为“虚构”参数,如果为true,表示既不是“显式”声明、也不是隐式声明在源文件中的参数,比如enum类的“values()”、“valueOf(String)”这是编译器“虚构”的系统方法。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics