原文地址: Java8反射获取方法的参数名称 类和接口
场景:在springmvc中,可以通过请求参数绑定controller方法对应的方法参数名
结论:接口获取不到方法参数名,但普通的类中的方法是可以获取到的
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());
}
}
执行结果
- 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
执行结果
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());
}
}
执行结果
在接口中,不管是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
执行结果
感谢
mercyblitz - 小马哥的讲解 博客地址 ( https://mercyblitz.github.io)