通过反射获取方法的参数名称(JDK8以上支持)
方法的参数名,在很多时候我们是需要反射得到的。但是在java8之前,代码编译为class文件后,方法参数的类型是固定的,但参数名称却丢失了,这和动态语言严重依赖参数名称形成了鲜明对比。(java是静态语言,所以入参名称叫什么其实无所谓的)。
虽然名称无所谓,但很多时候,我们需要此名称来做更好的安排,比如Myabtis的应用。下面介绍两种方式获取参数名:
一、通过jdk原生反射机制获取
import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.List; public class ParameterNameUtil { public static void main(String[] args) { List<String> paramterNames = getParameterNameJava8( ParameterNameUtil.class, "getParameterNameJava8"); paramterNames.forEach((x) -> System.out.println(x)); } public static List<String> getParameterNameJava8(Class clazz, String methodName) { List<String> paramterList = new ArrayList<>(); Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { if (methodName.equals(method.getName())) { //直接通过method就能拿到所有的参数 Parameter[] params = method.getParameters(); for (Parameter parameter : params) { paramterList.add(parameter.getName()); } } } return paramterList; } }
Java 8开始增加了类Parameter,在class文件中保留参数名,给反射带来了极大的便利。
二、通过spring的LocalVariableTableParameterNameDiscoverer获取
public static void main(String[] args) { List<String> paramterNames = getParamterName(ParameterNameUtil.class, "getParamterName"); paramterNames.forEach((x) -> System.out.println(x)); } public static List<String> getParamterName(Class clazz, String methodName) { LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer(); Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { if (methodName.equals(method.getName())) { //获取到该方法的参数们 String[] params = u.getParameterNames(method); return Arrays.asList(params); } } return null; }
备注:如果不用Class,而是通过spring注入的实例,然后instance.getClass.getDeclaredMethods()则无法得到参数名,调试时看到方法名称是通过jdk代理过的,拿不到参数名。
另外,能成功获取方法参数的名称需要满足两个条件:
- JDK版本必须是1.8及以上
- 编译时候必须有编译选项:javac -parameters打开,默认是关闭的
IDEA配置方法如下:
kancy