如何找到两个非接口类最近的公共超类

时间:2016-04-08 21:24:59

标签: java inheritance superclass

要找到最近的公共超类,给定两个非接口类ab,我会执行以下操作:

static Class<?> findClosestCommonSuper(final Class<?> a, final Class<?> b) {
    Iterator<Class<?>> pathA = pathFromObject(a).iterator();
    Iterator<Class<?>> pathB = pathFromObject(b).iterator();
    Class<?> res = Object.class;
    Class<?> c;
    while (pathA.hasNext() && pathB.hasNext()) {
        if ((c = pathA.next()) == pathB.next())
            res = c;
    }
    return res;
}

pathFromObject()返回表示继承链的List<Class<?>>,从Object.class开始:

static List<Class<?>> pathFromObject(Class<?> cl) {
    List<Class<?>> res = new ArrayList<>();
    while (cl != null) {
        res.add(cl);
        cl = cl.getSuperclass();
    }
    Collections.reverse(res);
    return res;
}

我的问题是:是否存在一些开箱即用的JDK解决方案?也许使用类加载器或某些特定功能。或者是一种不需要两次迭代的更好的算法。

2 个答案:

答案 0 :(得分:15)

我认为最简单的实现就是这个

static Class<?> findClosestCommonSuper(Class<?> a, Class<?> b) {
    while (!a.isAssignableFrom(b))
        a = a.getSuperclass();
    return a;
}

答案 1 :(得分:1)

没有JDK实用程序可以执行此操作。

这是一个有趣的采访问题。它基本上是在给定节点的情况下在树中的两个节点之间找到最低共同祖先的问题。典型的解决方案是队列。您交替验证然后添加每个节点的父节点。

类似的东西:

static Class<?> findClosestCommonSuper(final Class<?> a, final Class<?> b) {
    // Validation on the type of Class (interface, primitive, etc.) and != null

    Set<Class<?>> visited = new HashSet<>();
    Queue<Class<?>> queue = new LinkedList<>();
    queue.add(a);
    queue.add(b);

    do {
        // first iteration not empty
        Class<?> current = queue.poll();
        if (!visited.add(current)) {
            // already seen it, must be lowest in tree
            return current;
        }
        if (current.getSuperclass() != null) {
            queue.add(current.getSuperclass());
        }
    } while (!queue.isEmpty());

    throw new IllegalStateException("should never happen if the validation above is correct");
}

我相信这是您可以获得的最有效率,因为您不必不必要地遍历Object.class之前的完整路径。