2

我想调用具有参数接口的方法(使用反射) - 即:列表但具有列表的实现。例如:

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 是否也可能返回以接口为参数的方法?或者我必须编写自己的“方法搜索器”

谢谢你。

编辑: 这要复杂得多。我正在尝试在我的程序中编写类似“动态模块化架构”的东西。我有核心,它应该与其他模块通信。所以我不知道编程时的参数类,但在运行时。

 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;
        }

这个会比较好吗?

4

3 回答 3

4

我可能找到了解决方案——我必须编写自己的“方法搜索器”,它尊重接口实现和超类。它看起来像这样:

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 抛出“NoSuchMethodException”之后使用它(大约 5% 的情况,所以我不在乎速度。

于 2013-10-14T09:48:33.903 回答
1

你应该使用List类,而不是ArrayList.

Method method = Test1.class.getMethod("method", new Class[]{List.class});
于 2013-10-11T08:17:21.883 回答
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;
            }
        }
    }
于 2020-07-26T06:23:47.577 回答