在运行时找到方法'父母'的简单方法?

时间:2016-08-21 09:08:02

标签: java

我正在尝试找到一种在运行时检索方法的“父”的简单方法。 (可能使用反射)通过方法的“父”,我指的是在继承树中首先定义所述方法的类。理想情况下,这也适用于Generics。

示例:

import json
import time

while True:
    with open('/tmp/install-report.json') as json_data:
        d = json.load(json_data)
        for key, value in d.iteritems():
            print key, value
        time.sleep(1)

如果我想获得Class3#doSomething的'父母',它应该检索Class1和Class2。 Java中是否存在任何此类方法,甚至可能?

2 个答案:

答案 0 :(得分:0)

参考此question 它在接口上循环:for (Class<?> c : cls.getInterfaces()) ... 您还可以使用for (Class<?> c : cls.getClasses())

循环上课

答案 1 :(得分:0)

稍微繁琐的实施,但你应该能够拿起你需要的东西(只要你做你想做的事)并扔掉其余部分。基本上,我们在课堂上找到了相关的方法,如果没有找到,我们会返回(如果你想搜索父母,即使班级本身没有声明,那么继续搜索并且不返回)。然后我们递归直接超类树,直到我们到达Object。在此之后,基于我们发现的东西,我们分歧以寻求超级接口。

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class TestParent {

    public static void main(String[] args) {
        // prints Class1 and Class2
        System.out.println(getParents(Class3.class, "doSomething"));

        // prints Class5
        System.out.println(getParents(Class3.class, "run"));
    }

    private static List<Class> getParents(Class<?> type, String methodName) {
        Method method = getMethodByName(type, methodName);
        if (method == null)
            return Collections.emptyList();

        Class nextClass = type.getSuperclass();
        Class parent = null;

        while (!nextClass.equals(Object.class)) {

            if (hasMethod(nextClass, methodName, method)) {
                parent = nextClass;
            }

            nextClass = nextClass.getSuperclass();
        }

        List<Class> parents = new ArrayList<>();

        if (parent != null) {
            // search parent interfaces
            for (Class t : parent.getInterfaces()) {
                if (hasMethod(t, methodName, method)) {
                    parents.add(t);
                }
            }

            if (parents.isEmpty())
                parents.add(parent);

        } else {
            // search our interfaces
            for (Class t : type.getInterfaces()) {
                if (hasMethod(t, methodName, method)) {
                    parents.add(t);
                }
            }
        }

        return parents;
    }

    private static boolean equalMethod(Method m1, Method m2) {
        return m1.getName().equals(m2.getName()) && m1.getReturnType().equals(m2.getReturnType());
        // uncomment if parameter types must be the same
        //&& Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes());
    }

    private static boolean hasMethod(Class<?> type, String methodName, Method method) {
        Method m = getMethodByName(type, methodName);

        return m != null && equalMethod(method, m);
    }

    private static Method getMethodByName(Class<?> type, String methodName) {
        for (Method m : type.getDeclaredMethods()) {
            if (m.getName().equals(methodName)) {
                return m;
            }
        }

        return null;
    }

    public interface Class1<O> {
        void doSomething(O s);
    }

    public interface Class2 {
        void doSomething(String s);
    }

    public class Class3 extends Class4 implements Class1<String>, Class2 {
        public void doSomething(String s) {
            // Something
        }

        @Override
        void run() {

        }
    }

    public abstract class Class4 extends Class5 {
        abstract void run();
    }

    public abstract class Class5 {
        abstract void run();
    }
}