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

How do I find the nearest common superclass of two non-interface classes

要找到最近的公共超类,给定两个非接口 类 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() returns一个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 解决方案?也许使用类加载器或某些特定功能。或者不需要两次迭代的更好的算法。

我认为最简单的实现是这样

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

没有 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.

的完整路径