本文主要是介绍JDK8新特性-反射获取方法的参数名称,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在JDK8之前,java编译器会忽略我们编写代码时候设定的参数名,比如在mybatis框架中,我们可以使用@Param注解来让mybatis知道参数名。
public interface DemoMapper { List<Card> getCardList(@Param("cardIds") List<Integer> cardIds); Card getCard(@Param("cardId")int cardId);
}
很长一段时间里,Java程序员一直在发明不同的方式使得方法参数的名字能保留在Java字节码中,并且能够在运行时获取它们(比如Paranamer类库-Java 8开始增加了类Parameter,在class文件中保留参数名,给反射带来了极大的便利)。最终,在Java 8中把这个强烈要求的功能添加到语言层面(通过反射API与Parameter.getName()方法)与字节码文件(通过新版的javac的–parameters选项)中。
public class ParameterNames {public static void main(String[] args) throws Exception {Method method = ParameterNames.class.getMethod("main", String[].class);for (final Parameter parameter : method.getParameters()) {// 参数名称是否存在System.out.println("isNamePresent: " + parameter.isNamePresent());System.out.println("Parameter: " + parameter.getName());}}
}
如果不使用–parameters参数来编译这个类,然后运行这个类,会得到下面的输出:
isNamePresent: false
Parameter: arg0
如果使用–parameters参数来编译这个类,参数的真实名字将会显示出来:
isNamePresent: true
Parameter: args
项目中使用
–parameters
前后记得先 重新编译下项目代码(Build -> Rebuild Project)
还原Spring MVC获取参数名的场景
public static void main(String[] args) throws NoSuchMethodException {Method method = Main.class.getMethod("test1", String.class, Integer.class);MethodParameter nameParameter = new MethodParameter(method, 0);MethodParameter ageParameter = new MethodParameter(method, 1);// 打印输出:// 使用Parameter输出Parameter nameOriginParameter = nameParameter.getParameter();Parameter ageOriginParameter = ageParameter.getParameter();System.out.println("===================源生Parameter结果=====================");System.out.println(nameOriginParameter.getType() + "----" + nameOriginParameter.getName());System.out.println(ageOriginParameter.getType() + "----" + ageOriginParameter.getName());System.out.println("===================MethodParameter结果=====================");System.out.println(nameParameter.getParameterType() + "----" + nameParameter.getParameterName());System.out.println(ageParameter.getParameterType() + "----" + ageParameter.getParameterName());System.out.println("==============设置上ParameterNameDiscoverer后MethodParameter结果===============");ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();nameParameter.initParameterNameDiscovery(parameterNameDiscoverer);ageParameter.initParameterNameDiscovery(parameterNameDiscoverer);System.out.println(nameParameter.getParameterType() + "----" + nameParameter.getParameterName());System.out.println(ageParameter.getParameterType() + "----" + ageParameter.getParameterName());
}
输出结果:
===================源生Parameter结果=====================
class java.lang.String----arg0
class java.lang.Integer----arg1
===================MethodParameter结果=====================
class java.lang.String----null
class java.lang.Integer----null
==============设置上ParameterNameDiscoverer后MethodParameter结果===============
class java.lang.String----name
class java.lang.Integer----age
从结果能看出来:Spring MVC
借助ParameterNameDiscoverer
完成了方法参数名的获取,进而完成数据封装。关于ParameterNameDiscoverer
它的讲解,可先行参阅:【小家Spring】Spring标准处理组件大合集(ParameterNameDiscoverer、AutowireCandidateResolver、ResolvableType。。。)
Spring中获取方法参数名的工具LocalVariableTableParameterNameDiscoverer
public class Main {private static final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();public void testArguments(String test, Integer myInteger, boolean booleanTest) {}public void test() {}public static void main(String[] args) {Method[] methods = Main.class.getDeclaredMethods();for (Method method : methods) {String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);System.out.println("方法:" + method.getName() + " 参数为:" + Arrays.asList(parameterNames));for (Parameter parameter : method.getParameters()) {System.out.println(parameter.getName());}}}}
使用-parameters
获取方法参数名
最为简单直接的方式,Java8
源生支持:直接从java.lang.reflect.Parameter
就能获取到,形如这样:
public class MainTest2 {public static void main(String[] args) throws NoSuchMethodException {Method method = MainTest2.class.getMethod("testArgName", String.class, Integer.class);System.out.println("paramCount:" + method.getParameterCount());for (Parameter parameter : method.getParameters()) {System.out.println(parameter.getType().getName() + "-->" + parameter.getName());}}public String testArgName(String name, Integer age) {return null;}
}
输出:
paramCount:2
java.lang.String-->name
java.lang.Integer-->age
当然,它有两个最大的弊端:
- 必须Java8或以上(由于java8已经普及率非常高了,所以这个还好)
- 编译时候必须有编译选项:
-parameters
打开,默认是关闭的。(由于依赖编译参数,所以对迁移是不太友好的,这点比较致命)
指定-parameters
编译参数的方式:
-
手动命令方式编译:
javac -parameters XXX.java
-
IDE(以Idea为例)编译:
Settings -> Build,Execution,Deployment -> Compiler -> Java Compiler
- Additional command line parameters框中设置为-parameters
- Override compiler parameters per-module中新增一个module并设置 Compilation options值为-parameters
-
Maven编译:通过编译插件指定,保证项目迁移的正确性(
推荐
)
<!-- 编译环境在1.8编译 且附加编译参数:-parameters-->
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.0</version><configuration><compilerArgs><arg>-parameters</arg></compilerArgs><source>${java.version}</source><target>${java.version}</target><compilerVersion>${java.version}</compilerVersion><encoding>${project.build.sourceEncoding}</encoding></configuration>
</plugin>
References
- Apache Maven Project
- 通过反射获取方法参数名时遇到的小坑
- Java如何获取方法的参数名称?
- JDK8新特性:编译器保留方法参数名字
- 为何Spring MVC可获取到方法参数名,而MyBatis却不行?【享学Spring MVC】
这篇关于JDK8新特性-反射获取方法的参数名称的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!