代码之家  ›  专栏  ›  技术社区  ›  Alex Salauyou

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

  •  14
  • Alex Salauyou  · 技术社区  · 10 年前

    为了找到最近的公共超类,给定两个非接口类 a b ,我执行以下操作:

    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 回复  |  直到 10 年前
        1
  •  18
  •   Paul Boddington    10 年前

    我认为最简单的实现是

    static Class<?> findClosestCommonSuper(Class<?> a, Class<?> b) {
        while (!a.isAssignableFrom(b))
            a = a.getSuperclass();
        return a;
    }
    
        2
  •  1
  •   Savior    10 年前

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