温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java中怎么获取方法参数

发布时间:2021-07-23 16:49:03 来源:亿速云 阅读:714 作者:Leah 栏目:编程语言

这篇文章将为大家详细讲解有关Java中怎么获取方法参数,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

如果你的项目是实用maven构建,那么就可以加入几行配置,追加参数。

<plugin>       <artifactId>maven-compiler-plugin</artifactId>       <version>3.8.0</version>       <configuration>           <source>1.8</source>           <target>1.8</target>           <encoding>utf8</encoding>           <compilerArgs>               <arg>-parameters</arg>           </compilerArgs>       </configuration>   </plugin>

如果是用的IDEA等编辑器,也可以通过设置界面进行配置。不过不推荐这样,因为你的这些配置不好进行共享。

Java中怎么获取方法参数

在普通Java项目里,就可以通过下面的方式来获取反射数据。Method.getParameters这个方法是新加的。

public class Test {        public static void main(String[] args) throws Exception{         Class clazz = Class.forName("com.test.MethodParameterTest");         Method[] methods = clazz.getMethods();         Constructor[] constructors = clazz.getConstructors();         for (Constructor constructor : constructors) {             System.out.println("+++" + constructor.getName());             Parameter[] parameters = constructor.getParameters();             for (Parameter parameter : parameters) {                 printParameter(parameter);             }         }            System.out.println("------------------");         for (Method method : methods) {             System.out.println(method.getName());             Parameter[] parameters = method.getParameters();             for (Parameter parameter : parameters) {                 printParameter(parameter);             }         }     }        private static void printParameter(Parameter parameter) {         //参数名         System.out.println("\t\t" + parameter.getName());         //是否在源码中隐式声明的参数名         System.out.println("\t\t\t implicit:" + parameter.isImplicit());         //类文件中,是否存在参数名         System.out.println("\t\t\t namePresent:" + parameter.isNamePresent());         //是否为虚构参数         System.out.println("\t\t\t synthetic:" + parameter.isSynthetic());         System.out.println("\t\t\t VarArgs:" + parameter.isVarArgs());     } }

下面介绍几个方法的意义:

isImplicit()

参数是否为隐式声明在源文件中,比如内部类,默认构造函数(无参)其实在编译成class时将会把包含它的主类引用作为首个参数,此参数即为隐式声明。

如果为true,即表示有JDK编译器隐式生成在class文件中的方法参数,而source文件中并不可见。常规的普通方法,此值为false。

isNamePresent()

此参数在class文件中是否有此参数名;受制于在编译时是否指定了“-parameter”,对于指定此参数的编译文件,通常为true;对于JDK  内部类、默认编译的类,通常为false;此时你会发现,它们的参数名通常为表意名称:arg0、arg1等等,此时为false。

isSynthetic()

是否为“虚构”参数,如果为true,表示既不是“显式”声明、也不是隐式声明在源文件中的参数,比如enum类的“values()”、“valueOf(String)”这是编译器“虚构”的系统方法。

在Spring环境中,由于有工具类的支持,会更加方便一些。

public class SpringTest {        private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();           public static void main(String[] args) throws Exception{         Class clazz = Class.forName("com.test.MethodParameterTest");         Method[] methods = clazz.getMethods();         for (Method method : methods) {             System.out.println(method.getName());             //JDK 1.8 + is better.             String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);             if (parameterNames == null) {                 continue;             }             for (String pn : parameterNames) {                 System.out.println("\t\t" + pn);             }         }     } }

那Java版本低于1.8的时候,又是怎么获取的呢?我们可以参考Spring的LocalVariableTableParameterNameDiscoverer类。

public String[] getParameterNames(Method method) {         Method originalMethod = BridgeMethodResolver.findBridgedMethod(method);         return doGetParameterNames(originalMethod); } @Nullable private String[] doGetParameterNames(Executable executable) {         Class<?> declaringClass = executable.getDeclaringClass();         Map<Executable, String[]> map = this.parameterNamesCache.computeIfAbsent(declaringClass, this::inspectClass);         return (map != NO_DEBUG_INFO_MAP ? map.get(executable) : null); }

最后就走到了inspectClass方法中。

private Map<Executable, String[]> inspectClass(Class<?> clazz) {         InputStream is = clazz.getResourceAsStream(ClassUtils.getClassFileName(clazz));         if (is == null) {             // We couldn't load the class file, which is not fatal as it             // simply means this method of discovering parameter names won't work.             if (logger.isDebugEnabled()) {                 logger.debug("Cannot find '.class' file for class [" + clazz +                         "] - unable to determine constructor/method parameter names");             }             return NO_DEBUG_INFO_MAP;         }         try {             ClassReader classReader = new ClassReader(is);             Map<Executable, String[]> map = new ConcurrentHashMap<>(32);             classReader.accept(new ParameterNameDiscoveringVisitor(clazz, map), 0);             return map;         }         ...

可以看到,这种情况下,Spring是通过直接读取class文件进行解析的。实际上是通过读取LocalVariableTable中的数据进行获取的。如果你编译的时候没有加入这些debug选项,同样也拿不到方法参数的具体名称。

总结一下

  • Java8以前,读取Class中的LocalVariableTable属性表,需要编译时加入参数-g或者-g:vars  获取方法局部变量调试信息;

  • Java8及其以后,通过java.lang.reflect.Parameter#getName即可获取,但需要编译时加入参数-parameters参数。

关于Java中怎么获取方法参数就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI