繁体   English   中英

Java:获取带有接口参数的方法及其实现

[英]Java: Get method with interface parameter with its implementation

我想调用具有参数接口的方法(使用反射) - 即: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”

谢谢。

编辑:它要复杂得多。 我正在尝试在我的程序中编写类似“动态模块化架构”的内容。 我有核心,它应该与其他模块通信。 所以我在编程时不知道 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;
        }

是不是更好?

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

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% 的情况下,所以我不关心速度。

您应该使用List类,而不是ArrayList

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM