Java 8新特性 - (8)方法参数反射

分享到:

文章目录

方法的参数名,在很多时候我们是需要反射得到的。但是在java8之前,代码编译为class文件后,方法参数的类型是固定的,但参数名称却丢失了,这和动态语言严重依赖参数名称形成了鲜明对比。(java是静态语言,所以入参名称叫什么其实无所谓的)。虽然名称无所谓,但很多时候,我们需要此名称来做更好的安排.

比如mybatis的Dao层接口方法,需要特意用个注解@Param来显示标识出参数名。所以java8来了,带来的新特性解决了这一问题。

获取方法参数名称有3种方法:

采用javassit包获取

很麻烦,参考其他网上文章

通过spring的LocalVariableTableParameterNameDiscoverer

 1public static void main(String[] args) {
 2    List<String> paramterNames = getParamterName(StaffMark.class, "fun1");
 3    paramterNames.forEach((x) -> System.out.println(x));
 4}
 5
 6public static void fun1(String aaa, Integer bbb) {
 7
 8}
 9
10public static List<String> getParamterName(Class clazz, String methodName) {
11    LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
12    Method[] methods = clazz.getDeclaredMethods();
13    for (Method method : methods) {
14        if (methodName.equals(method.getName())) {
15            //获取到该方法的参数们
16            String[] params = u.getParameterNames(method);
17            return Arrays.asList(params);
18        }
19    }
20    return null;
21}

输出:

1aaa
2bbb

备注:如果不用Class,而是通过spring注入的实例,然后instance.getClass.getDeclaredMethods()则无法得到参数名,调试时看到方法名称是通过jdk代理过的,拿不到参数名。

通过Java8的Parameter类

Java 8开始在class文件中保留参数名,给反射带来了极大的便利。jdk8增加了类Parameter

 1public static void main(String[] args) {
 2    List<String> paramterNames = getParameterNameJava8(StaffMark.class, "fun1");
 3    paramterNames.forEach((x) -> System.out.println(x));
 4}
 5
 6public static void fun1(String aaa, Integer bbb) {
 7
 8}
 9
10public static List<String> getParameterNameJava8(Class clazz, String methodName) {
11    List<String> paramterList = new ArrayList<>();
12    Method[] methods = clazz.getDeclaredMethods();
13    for (Method method : methods) {
14        if (methodName.equals(method.getName())) {
15            //直接通过method就能拿到所有的参数
16            Parameter[] params = method.getParameters();
17            for (Parameter parameter : params) {
18                paramterList.add(parameter.getName());
19            }
20
21        }
22    }
23
24    return paramterList;
25}

执行后的输出:

1arg0
2arg1

可以看到输出的不是想要的参数名。因为java8为了保持向下兼容,默认编译是不能获取到参数名称的。需要满足下面两个条件

  • JDK版本必须是1.8及以上
  • 编译时候必须有编译选项:javac -parameters打开,默认是关闭的

在idea设置保留参数名的方法:在 preferences-》Java Compiler->设置模块字节码版本1.8,Javac Options中的 Additional command line parameters: -parameters

这样设置之后,我们再运行上面代码,发现输出的结果为:

1aaa
2bbb

参考: