Java関数パラメータ名を取得する別の方法
9690 ワード
Javaメソッドのパラメータ名の取得について(ここではjava 1.8以前のバージョンを指し、java 1.8はすでに関連するオリジナルメソッドを提供している)、ネット上で多くの文章を見つけることができて、この文章は比較的に全面的に述べています:《Javaが関数パラメータ名を取得するいくつかの方法》、asm、javasistなどのサードパーティライブラリを借りる以外ありません.
私のプロジェクトにもこの需要がありますが、この文章を読むとやはり面倒だと思います.この小さな需要のために、依存ライブラリを多く導入するのは、少しお得ではありません.
私はaxis 2に詳しいので、axis 2でclientコードを生成する際にも方法のパラメータ名を取得する必要があることを知っていて、そこでソースコードを分析することによってaxis 2の実現コードを見つけました.axis 2 javaパラメータ名を取得する実装コードのpackageは
そこで私はこのコードを個別にコピーしました(完全なコードはgitee倉庫を参照してください:https://gitee.com/l0km/common-java/tree/master/common-base/src/main/java/org/apache/bytecode)に基づいてクラス
ParameterNames.java
完全なコードはgiteeウェアハウスを参照してください:https://gitee.com/l0km/common-java/blob/master/common-base/src/main/java/net/gdface/utils/ParameterNames.java
呼び出し例:
完全なコードはgiteeウェアハウスを参照してください.https://gitee.com/l0km/common-java/blob/master/common-base/src/test/java/net/gdface/common/ClassTest.java
私のプロジェクトにもこの需要がありますが、この文章を読むとやはり面倒だと思います.この小さな需要のために、依存ライブラリを多く導入するのは、少しお得ではありません.
私は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