Java获取函数参数名称的另一种方法

关于获取java 方法的参数名(这里指java 1.8以前的版本,java 1.8已经提供了相关的原生方法),网上可以找到不少文章,这篇文章讲得比较全面了:《Java获取函数参数名称的几种方法》,无外乎是借用asm,javasist等第三方库。

我的项目中也有此需求,看了这篇文章还是觉得比较麻烦,为了这个小小的需求,要多引入一系列依赖库,有点不划算。

我对axis2比较熟悉,知道axis2中在生成client代码时也需要获取方法的参数名,于是通过分析源码找到了axis2的实现代码。
axis2获取java参数名的实现代码的package为org.apache.axis2.description.java2wsdl.bytecode,在axis2核心jar包axis2-kernel-1.6.2.jar中(源码下载地址:axis2-kernel-1.6.2-sources.jar)
好就好在这个package没有引用package之外的代码,所以可以单独提取出来独立调用。

于是我把这部分代码单独复制出来(完整代码参见gitee仓库:
https://gitee.com/l0km/common-java/tree/master/common-base/src/main/java/org/apache/bytecode),并在此基础上封装了一个类ParameterNames,方便调用:

ParameterNames.java

package net.gdface.utils;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import net.gdface.utils.Assert;

import org.apache.bytecode.ChainedParamReader;

/** * 获取构造函数或方法的参数名
* 当不能获取参数名的情况下, * {@link returnFakeNameIfFail}为{@code false}时返回{@code null},否则返回返回arg,arg2...格式的替代名
* {@link returnFakeNameIfFail}默认为{@code true} * @author guyadong * */
public class ParameterNames { private final Map, ChainedParamReader> readers = new HashMap, ChainedParamReader>(); private final Class clazz; /** 当获取无法参数名时是否返回arg,arg2...格式的替代名字 */ private boolean returnFakeNameIfFail = true; public ParameterNames setReturnFakeNameIfFail(boolean returnFakeNameIfFail) { this.returnFakeNameIfFail = returnFakeNameIfFail; return this; } /** * @param clazz 要构造函数或方法的参数名的类,为{@code null}时所有getParameterNames方法返回{@code null} */ public ParameterNames(Class clazz) { this.clazz = clazz; if(null != clazz){ try { Class c = clazz; do { readers.put(c, new ChainedParamReader(c)); } while (null != (c = c.getSuperclass())); } catch (IOException e) { throw new RuntimeException(e); } } } /** * 获取构造函数或方法的参数名 * @param reader * @param member 构造函数或方法对象 * @return */ private final String[] getParameterNames(ChainedParamReader reader, Member member) { String [] parameterNames = null; int paramCount ; if (member instanceof Method){ parameterNames = reader.getParameterNames((Method) member); paramCount = ((Method) member).getParameterTypes().length; } else if (member instanceof Constructor){ parameterNames = reader.getParameterNames((Constructor) member); paramCount = ((Constructor) member).getParameterTypes().length; } else { throw new IllegalArgumentException("member type must be Method or Constructor"); } if(this.returnFakeNameIfFail){ if (null == parameterNames) { parameterNames = new String[paramCount]; for (int i = 0; i < parameterNames.length; i++) parameterNames[i] = String.format("arg%d", i); } } return parameterNames; } /** * 获取构造函数或方法的参数名 * @param member 构造函数或方法对象 * @return * @see #getParameterNames(ChainedParamReader, Member) */ public final String[] getParameterNames(Member member) { if(null == clazz){ return null; } Assert.notNull(member, "member"); Class declaringClass = member.getDeclaringClass(); ChainedParamReader reader; if (null == (reader = readers.get(declaringClass))) { throw new IllegalArgumentException(String.format("%s is not member of %s", member.toString(), declaringClass.getName())); } return getParameterNames(reader, member); } /** * 获取构造函数或方法的参数名
* {@code name}为{@code null}时,获取构造函数的参数名 * @param name 方法名 * @param parameterTypes 构造函数或方法的参数类型 * @return * @throws NoSuchMethodException * @see #getParameterNames(String, Class) */
public final String[] getParameterNames(String name, Class[] parameterTypes) throws NoSuchMethodException { if(null == clazz){ return null; } try { Member member = null == name ? clazz.getConstructor(parameterTypes) : clazz.getMethod(name, parameterTypes); return getParameterNames(member); } catch (SecurityException e) { throw new IllegalArgumentException(e); } } }

完整代码参见gitee仓库:https://gitee.com/l0km/common-java/blob/master/common-base/src/main/java/net/gdface/utils/ParameterNames.java

调用示例:

    private static void outputParameterNames(Method method){
        // 抽象方法不能正确获取参数名,只能用假名替代
        System.out.printf("%s abstract = %b\n parameter names:",
                method.getName(),
                Modifier.isAbstract(method.getModifiers()));
        ParameterNames pt = new ParameterNames(method.getDeclaringClass());
        String[] names = pt.getParameterNames(method);
        for(String name:names){
            System.out.print(name + ",");
        }
        System.out.println();
    }

完整的代码参见gitee仓库:
https://gitee.com/l0km/common-java/blob/master/common-base/src/test/java/net/gdface/common/ClassTest.java

你可能感兴趣的:(java)