Java8反射获取方法的参数名称 类和接口

Java8反射获取方法参数名
本文介绍如何在Java8中使用反射获取类和接口方法的参数名称,包括使用spring的ParameterNameDiscoverer和Java反射Parameter类。演示了在默认情况下无法获取参数名的问题,并提供了解决方案,即通过增加javac-parameters参数来实现。

java8反射获取方法的参数名称 类和接口

1.简要说明

  • 演示springboot版本为2.0.3.RELEASE

  • 为啥要分java类java接口两种进行参数获取的演示

    • java类编译成class文件后,方法签名参数 会保存在字节码文件中,通过一些字节码的解析框架可以获取方法的参数名称
    • java接口编译成class文件后,默认不会保存方法的参数签名,jdk这么设计,因为接口的参数名称一般没有意义,但是现在的技术发展导致一些框架需要用到接口的参数名称
      • spring openFeign 中使用接口进行编程
      • mybatis 中的 Mapper 文件接口
      • 其他一些动态代理接口的编程方式
  • 在Java8之后,反射包package java.lang.reflect;新加入了Parameter类,可以解决这类问题

指导文章
https://docs.oracle.com/javase/tutorial/reflect/member/methodparameterreflection.html
Java 8 + 增加 javac -parameters 参数

大前提:必须是 Java 8

package java.lang.reflect;
...
/**
 * Information about method parameters.
 *
 * A {@code Parameter} provides information about method parameters,
 * including its name and modifiers.  It also provides an alternate
 * means of obtaining attributes for the parameter.
 *
 * @since 1.8
 */
public final class Parameter implements AnnotatedElement {

    private final String name;
    private final int modifiers;
    private final Executable executable;
    private final int index;
    ...
}

2.java类获取方法参数名称

测试代码

  • 使用spring中的ParameterNameDiscoverer类获取方法的参数
  • 使用传统的java反射获取参数名称
/**
 * 测试反射获取类方法参数
 */
public class ParameterDemo {
    public String say(String message){
        return "hello world:"+message;
    }

    public static void main(String[] args) {
        Method method = ReflectionUtils.findMethod(ParameterDemo.class,"say",String.class);
        ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
        String[] parameterNames = discoverer.getParameterNames(method);
        Stream.of(discoverer.getParameterNames(method)).forEach(System.out::println);
        methodTest();
    }

    public static void methodTest() {
        Method method = ReflectionUtils.findMethod(ParameterDemo.class,"say",String.class);
        Parameter parameter = method.getParameters()[0];
        System.out.println(parameter.getName());
    }
}

执行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xsjeny78-1570846606132)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1570845320634.png)]

  • spring通过字节码解析技术获取到了方法的参数名称

  • 传统的反射方法无法获取参数名称

解决方法

增加 javac -parameters 参数

通过maven的方式

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <debug>true</debug>
                    <debuglevel>lines,vars,source</debuglevel>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>

关键代码

<compilerArgs>
     <arg>-parameters</arg>
</compilerArgs>

先 clean 再 compiler
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5bJrJBto-1570846606132)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1570846353164.png)]

执行结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o9LAxfsl-1570846606133)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1570846400305.png)]

3.接口获取方法参数名称

测试代码

/**
 * 测试反射获取接口方法参数
 */
public interface ParameterInterfaceDemo {
    String say(String message);

    public static void main(String[] args) {
        Method method = ReflectionUtils.findMethod(ParameterInterfaceDemo.class,"say",String.class);
        ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
        String[] parameterNames = discoverer.getParameterNames(method);
        try {
            Stream.of(discoverer.getParameterNames(method)).forEach(System.out::println);
        }catch (Exception e){
            e.printStackTrace();
        }
        methodTest();
    }

    public static void methodTest() {
        Method method = ReflectionUtils.findMethod(ParameterInterfaceDemo.class,"say",String.class);
        Parameter parameter = method.getParameters()[0];
        System.out.println(parameter.getName());
    }
}

执行结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iXSMAlUj-1570846606133)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1570845289586.png)]
在接口中,不管是spring通过字节码技术还是传统的反射方法都无法获取

解决方法

增加 javac -parameters 参数

通过maven的方式

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <debug>true</debug>
                    <debuglevel>lines,vars,source</debuglevel>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>

关键代码

<compilerArgs>
     <arg>-parameters</arg>
</compilerArgs>

先 clean 再 compiler
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LS56BiId-1570846606134)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1570846353164.png)]

执行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RskZ22b1-1570846606134)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1570846400305.png)]

感谢

mercyblitz - 小马哥的讲解 博客地址 (https://mercyblitz.github.io)

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值