查找类以递归方式扩展或实现的所有类和接口

cod*_*het 17 java class jboss-arquillian

我想知道是否有一种简单的方法来确定Java类以递归方式扩展或实现的完整类型列表?

例如:

class Foo extends Bar implements I1, I2 {...}
class Bar implements I3 {...}
interface I1 extends I4, I5 {...}
interface I2 {...}
interface I3 {...}
interface I4 {...}
interface I5 {...}

class ClassUtil {
    public static Set<Class<?>> getAllExtendedOrImplementedTypesRecursively(Class<?> clazz){
        ???
    }
}

import static org.junit.Assert.*;
public class ClassUtilTest {
    @Test
    public void shouldEqualClasses(){
        Set<Class<?>> types = ClassUtil.getAllExtendedOrImplementedTypesRecursively(Foo.class);
        Set<Class<?>> checklist = new HashSet<>();
        checklist.add(Foo.class);
        checklist.add(Bar.class);
        checklist.add(I1.class);
        checklist.add(I2.class);
        checklist.add(I3.class);
        checklist.add(I4.class);
        checklist.add(I5.class);
        assertTrue(checklist.containsAll(types));
        assertTrue(types.containsAll(checklist));
    }
}
Run Code Online (Sandbox Code Playgroud)

想想Arquillian ShrinkWrap创作助手.

更新:由于Class对象没有实现Comparable>我还需要找到一种创建Set(或类似类)的方法,而不需要实现Comparable接口(例如,仅依赖于类对象的hashcode).

更新:更改测试以使用hashset.DERP.

hig*_*aro 12

该方法的以下实现执行OP所需的操作,它遍历每个类和接口的继承层次结构:

public static Set<Class<?>> getAllExtendedOrImplementedTypesRecursively(Class<?> clazz) {
    List<Class<?>> res = new ArrayList<>();

    do {
        res.add(clazz);

        // First, add all the interfaces implemented by this class
        Class<?>[] interfaces = clazz.getInterfaces();
        if (interfaces.length > 0) {
            res.addAll(Arrays.asList(interfaces));

            for (Class<?> interfaze : interfaces) {
                res.addAll(getAllExtendedOrImplementedTypesRecursively(interfaze));
            }
        }

        // Add the super class
        Class<?> superClass = clazz.getSuperclass();

        // Interfaces does not have java,lang.Object as superclass, they have null, so break the cycle and return
        if (superClass == null) {
            break;
        }

        // Now inspect the superclass 
        clazz = superClass;
    } while (!"java.lang.Object".equals(clazz.getCanonicalName()));

    return new HashSet<Class<?>>(res);
}    
Run Code Online (Sandbox Code Playgroud)

我测试过JFrame.class,我得到了以下内容:

Set<Class<?>> classes = getAllExtendedOrImplementedTypesRecursively(JFrame.class);
for (Class<?> clazz : classes) {
    System.out.println(clazz.getName());
}
Run Code Online (Sandbox Code Playgroud)

输出:

java.awt.Container
java.awt.Frame
javax.swing.JFrame
javax.swing.TransferHandler$HasGetTransferHandler
java.awt.Window
javax.accessibility.Accessible
javax.swing.RootPaneContainer
java.awt.Component
javax.swing.WindowConstants
java.io.Serializable
java.awt.MenuContainer
java.awt.image.ImageObserver
Run Code Online (Sandbox Code Playgroud)

更新:对于OP的测试用例,它打印:

test.I5
test.Bar
test.I2
test.I1
test.Foo
test.I3
test.I4
Run Code Online (Sandbox Code Playgroud)

  • `getAllExtendedOrImplementedTypesRecursively ThatWeBelieveToBeUsefulForTheRestOfTheProgramWithoutCrashingTheJvmOrBraggingAboutOurLongMethodName` (2认同)

TA *_*yen 10

Apache Common Lang中有一个ClassUtils,它有你想要的2种方法..getAllSuperClasses()和.getAllInterfaces().

  • 它是开源的,因此,您可以借用它并嵌入到您的代码集中,直到您准备接受整个库为止.祝好运. (3认同)
  • 这似乎提供了一个可行的解决方案,但我不希望依赖整个库(即使我最终将依赖它). (2认同)