Полное рабочее решение, насколько мне известно
- BFS каждой иерархии классов идет "вверх" - результат в LinkedHashSet (сохранить порядок + без дубликатов)
- Пересекайте каждый набор со следующим, чтобы найти что-то общее, снова LinkedHashSet для сохранения порядка
- Оставшийся «упорядоченный» набор - это общие предки, первый в списке «ближайший», последний - самый дальний.
- Пустой список не подразумевает никаких предков (кроме объекта)
Код
private static Set<Class<?>> getClassesBfs(Class<?> clazz) {
Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
Set<Class<?>> nextLevel = new LinkedHashSet<Class<?>>();
nextLevel.add(clazz);
do {
classes.addAll(nextLevel);
Set<Class<?>> thisLevel = new LinkedHashSet<Class<?>>(nextLevel);
nextLevel.clear();
for (Class<?> each : thisLevel) {
Class<?> superClass = each.getSuperclass();
if (superClass != null && superClass != Object.class) {
nextLevel.add(superClass);
}
for (Class<?> eachInt : each.getInterfaces()) {
nextLevel.add(eachInt);
}
}
} while (!nextLevel.isEmpty());
return classes;
}
private static List<Class<?>> commonSuperClass(Class<?>... classes) {
// start off with set from first hierarchy
Set<Class<?>> rollingIntersect = new LinkedHashSet<Class<?>>(
getClassesBfs(classes[0]));
// intersect with next
for (int i = 1; i < classes.length; i++) {
rollingIntersect.retainAll(getClassesBfs(classes[i]));
}
return new LinkedList<Class<?>>(rollingIntersect);
}
Методы поддержки и испытания
private static void test(Class<?>... classes) {
System.out.println("Common ancestor for "
+ simpleClassList(Arrays.asList(classes)) + ", Result => "
+ simpleClassList(commonSuperClass(classes)));
}
private static String simpleClassList(Collection<Class<?>> classes) {
StringBuilder builder = new StringBuilder();
for (Class<?> clazz : classes) {
builder.append(clazz.getSimpleName());
builder.append(",");
}
return builder.toString();
}
public static void main(String[] args) {
test(A.class, AImpl.class);
test(A.class, B.class, C.class);
test(A.class, AB.class);
test(AImpl.class, ABImpl.class);
test(ABImpl.class, ABImpl2.class);
test(AImpl.class, ABImpl.class, ABImpl2.class);
test(ABImpl.class, ABImpl2.class, BCImpl.class);
test(AImpl.class, ABImpl.class, ABImpl2.class, BCImpl.class);
test(AB.class, ABImpl.class);
}
выход
Common ancestor for A,AImpl,, Result => A,
Common ancestor for A,B,C,, Result =>
Common ancestor for A,AB,, Result => A,
Common ancestor for AImpl,ABImpl,, Result => A,
Common ancestor for ABImpl,ABImpl2,, Result => A,B,
Common ancestor for AImpl,ABImpl,ABImpl2,, Result => A,
Common ancestor for ABImpl,ABImpl2,BCImpl,, Result => B,
Common ancestor for AImpl,ABImpl,ABImpl2,BCImpl,, Result =>
Common ancestor for AB,ABImpl,, Result => AB,A,B,