Java:使用接口参数获取方法及其实现

时间:2013-10-11 08:06:46

标签: java reflection

我想调用具有参数Interface的方法(使用反射) - 即:List但是使用List的实现。 例如:

public class Test {

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Test1.class.getMethod("method", new Class[]{ArrayList.class});

    }

    public class Test1 {

        public void method(List list) {
            System.out.println("method");
        }
    }
}

我得到NoSuchMethodException。在这种情况下我知道我得到了哪些参数,问题是当我不“静态地”知道参数类型时我想要使用它。

getMethod是否可能返回具有接口作为参数的方法?或者我必须写自己的“methodsearcher”

谢谢。

修改 这要复杂得多。我正在尝试在我的程序中编写类似“动态模块化架构”的东西。我有Core,它应该与其他模块通信。所以我不知道编程时间中的params类,而是在运行时。

 public Object processMessage(String target, String methodName, List<Object> params, Object returnNonExist) {
    Module m = modules.get(target);
    if (m == null) {
        return returnNonExist;
    } else {
        Class[] paramsTypes = new Class[params.size()];
        for (int i = 0; i < params.size(); i++) {
            paramsTypes[i] = params.get(i).getClass();
            }
        }
        try {
            Method method = m.getClass().getMethod(methodName, paramsTypes);
            Object result = method.invoke(m, params.toArray());
            return result;
        }

它更好吗?

3 个答案:

答案 0 :(得分:3)

我可能找到了解决方案 - 我必须编写自己的&#34;方法搜索器&#34;哪个方面的接口实现和超级声明。它看起来像这样:

public static Method findMethod(Object m, String methodName, Class[] paramsTypes) {
    Method[] metody = m.getClass().getDeclaredMethods();
    List<Method> sameNames = new ArrayList<Method>();
    // filter other names
    for (Method meth : metody) {
        if (meth.getName().equals(methodName)) {
            sameNames.add(meth);
        }
    }
    // lets find best candidate
    if (sameNames.isEmpty()) {
        return null;
    } else {
        // filter other count of parameters
        List<Method> sameCountOfParameters = new ArrayList<Method>();
        for (Method meth : sameNames) {
            if (meth.getParameterTypes().length == paramsTypes.length) {
                sameCountOfParameters.add(meth);
            }
        }
        if (sameCountOfParameters.isEmpty()) {
            return null;
        } else {
            for (Method meth : sameCountOfParameters) {
                // first one, which is suitable is the best
                Class<?>[] params = meth.getParameterTypes();
                boolean good = true;
                for (int i = 0; i < params.length && good; i++) {
                    if (params[i].isInterface() && Arrays.asList(paramsTypes[i].getInterfaces()).contains(params[i])) {
                        //if i-th paramater type is Interface and we search method with its implementation
                        good = true;
                        continue;
                    } else {
                        // if we call it with subclass and parameter typ is superclass
                        if (paramsTypes[i].getSuperclass().equals(params[i])) {
                            good = true;
                            continue;
                        }
                    }
                    good = false;
                }
                if (good) {
                    return meth;
                }
            }
        }
    }
    return null;
}

我在标准的getMethod抛出后使用它&#34; NoSuchMethodException&#34; (大约5%的情况,所以我不关心速度。

答案 1 :(得分:1)

您应该使用List课程,而不是ArrayList

Method method = Test1.class.getMethod("method", new Class[]{List.class});

答案 2 :(得分:1)

@radeczek的很好答案。我将其扩展为可用于子类...

    public Method findMethod(String name, Class<?>[] paramsTypes) {
        
        Method[] methods = object.getClass().getMethods();
        
        List<Method> sameNames = new ArrayList<Method>();
        
        // filter other names
        for (Method m : methods) {
            if (m.getName().equals(name)) {
                sameNames.add(m);
            }
        }
        
        // lets find best candidate
        if (sameNames.isEmpty()) {
            return null;
            
        } else {
            
            // filter other count of parameters
            List<Method> sameCountOfParameters = new ArrayList<Method>();
            for (Method m : sameNames) {
                
                if (m.getParameterTypes().length == paramsTypes.length) {
                    sameCountOfParameters.add(m);
                }
            }
            
            if (sameCountOfParameters.isEmpty()) {
                return null;
                
                
            } else {
                for (Method m : sameCountOfParameters) {
                    
                    // first one, which is suitable is the best
                    Class<?>[] params = m.getParameterTypes();
                    
                    boolean good = true;
                    
                    for (int i = 0; i < params.length && good; i++) {
                        
                        // Recurse into subclasses 
                        good = findSubclass(paramsTypes[i],params[i]);
                    }
                    if (good) {
                        return m;
                    }
                }
            }
        }
        return null;
    }
    
    /**
     * Recursive check for interfaces of superclasses. 
     * 
     * @param paramType
     * @param param
     * @return
     */
    private boolean findSubclass(Class<?> paramType, Class<?> param) {
        
        if (param.isInterface() && Arrays.asList(paramType.getInterfaces()).contains(param)) {
            return true;
        } else {
            
            if (paramType.getSuperclass() != null) {
                return findSubclass(paramType.getSuperclass(), param);
            } else {
                return false;
            }
        }
    }