Java関数パラメータ名を取得する別の方法

9690 ワード

Javaメソッドのパラメータ名の取得について(ここではjava 1.8以前のバージョンを指し、java 1.8はすでに関連するオリジナルメソッドを提供している)、ネット上で多くの文章を見つけることができて、この文章は比較的に全面的に述べています:《Javaが関数パラメータ名を取得するいくつかの方法》、asm、javasistなどのサードパーティライブラリを借りる以外ありません.
私のプロジェクトにもこの需要がありますが、この文章を読むとやはり面倒だと思います.この小さな需要のために、依存ライブラリを多く導入するのは、少しお得ではありません.
私はaxis 2に詳しいので、axis 2でclientコードを生成する際にも方法のパラメータ名を取得する必要があることを知っていて、そこでソースコードを分析することによってaxis 2の実現コードを見つけました.axis 2 javaパラメータ名を取得する実装コードのpackageはorg.apache.axis2.description.java2wsdl.bytecodeであり、axis 2コアjarパッケージaxis 2-kernel-1.6.2.jar(ソースコードダウンロードアドレス:axis 2-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
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