比较方法参数类型,具有特定签名的类的过滤方法

时间:2013-12-11 16:11:46

标签: java reflection methods filter

想要对符合签名的方法进行分组。因此给定Class clz,返回类型类R和参数类型Class [] argsCLasses的列表,用clz中的匹配方法填充地图。我将这些方法存储在一个映射中,并将该映射用于使用用户提供的参数调用该方法。

使用这个地图我不需要大的case语句,只需通过匹配名称获取Method,然后调用它。

示例,

class Foo {

    public void method(String a, String b, int i) {

    }

    public void method2(String a2, String b2, int i2) {

    }

    public void method3(String a2, int i2) {

    }

    public void method4(String a2, String b2, int i2) {

    }

}

如果我想匹配[String,String,Integer],方法1,2和4是匹配。

我有什么:

import org.apache.log4j.Logger;

public class ReflectUtils {     private static final Logger logger = Logger.getLogger(ReflectUtils.class);

public static String fillMethods(Class clz, Class[] argsCLasses, Map<String, Method> methods) {
    String rtn = null;
    synchronized (methods) {

        synchronized (clz) {
            try {
                Method[] methodsAvail = clz.getMethods();
                boolean match = false;
                for (Method mtd : methodsAvail) {
                    Class rtnM = mtd.getReturnType();
                    // if (rtnM.isAssignableFrom( rtnType)) {
                    // continue;
                    // }
                    Class[] args = mtd.getParameterTypes();
                    if (argsCLasses.length != args.length) {
                        continue;
                    }
                    match = true;
                    for (int i = 0; i < argsCLasses.length; i++) {
                        if (args[i] != argsCLasses[i]) {
                            match = false;
                        }
                    }
                    if(match){
                        methods.put(mtd.getName(), mtd);
                    }
                }
            } catch (Throwable e) {
                rtn = "ERROR :" + e;
                logger.error("Err fill methods :" + e, e);

            }
        }
    }
    return rtn;
}

public static void main(String[] args) {
    Class[] argsCLasses = new Class[] { String.class, String.class, Integer.class };
    Map<String, Method> methods = new HashMap<String, Method>();
    // Class clz, Class[] argsCLasses, Map<String, Method> methods
    fillMethods(Foo.class, argsCLasses, methods);
    System.out.println(methods);
    System.out.println();
    System.out.println(methods.keySet());
}

}

这已经有了什么吗?

在内循环中

if (args[i] != argsCLasses[i]) 

我应该使用isAssignableFrom吗?或者其他什么来看看它是否匹配的arg?还有什么要比较以查看方法是否符合标准?

2 个答案:

答案 0 :(得分:1)

当参数不符合方法签名时,您将继续内循环。但你必须继续外循环。

您可以使用标签来执行此操作:

outerLoop: // Label
for (Method mtd : methodsAvail) {
    Class rtnM = mtd.getReturnType();
    Class[] args = mtd.getParameterTypes();
    if (argsCLasses.length != args.length) {
        continue;
    }
    for (int i = 0; i < argsCLasses.length; i++) {
        if (args[i] != argsCLasses[i]) {
            continue outerLoop;  // continue to the label outerLoop
        }
    }
    methods.put(mtd.getName(), mtd);
}

答案 1 :(得分:1)

您可以使用isAssignableFrom来匹配参数。您可能还需要将基元类型与其包装器匹配。我的实用程序库中的示例:

private static boolean _matches(Class inputParam, Class<?> declaredArgumentParam) {
    boolean matches = true;
    if (!declaredParam.isAssignableFrom(inputParam)) {
        if(
            (inputParam.isPrimitive() && Primitives.wrap(inputParam) == declaredArgumentParam) ||
            (declaredArgumentParam.isPrimitive() && Primitives.wrap(declaredArgumentParam) == inputParam)
            ){
        }else{
            matches = false;
        }
    }
    return matches;
}

github的完整资料来源:HavingMethodSignature.java