如何在Java中找到给定类的所有子类(或给定接口的所有实现者)? 到目前为止,我有一个方法来做到这一点,但我发现它相当低效(至少可以说)。 方法是:

获取类路径上存在的所有类名的列表 加载每个类并测试它是否是所需类或接口的子类或实现者

在Eclipse中,有一个很好的特性叫做类型层次结构,它能够非常有效地显示这一点。 如何以编程的方式进行呢?


当前回答

还要注意的是,这当然只能找到当前类路径中存在的所有子类。想必这对于你目前所看到的是可以的,而且你也有可能考虑过这一点,但如果你在任何时候发布了一个非最终类(对于不同程度的“狂野”),那么其他人已经编写了他们自己的子类,而你不知道这是完全可行的。

Thus if you happened to be wanting to see all subclasses because you want to make a change and are going to see how it affects subclasses' behaviour - then bear in mind the subclasses that you can't see. Ideally all of your non-private methods, and the class itself should be well-documented; make changes according to this documentation without changing the semantics of methods/non-private fields and your changes should be backwards-compatible, for any subclass that followed your definition of the superclass at least.

其他回答

你可以使用org。然后,创建一个reflections类的对象。使用此对象,您可以获得给定类的所有子类的列表。 https://www.javadoc.io/doc/org.reflections/reflections/0.9.10/org/reflections/Reflections.html

    Reflections reflections = new Reflections("my.project.prefix");
    System.out.println(reflections.getSubTypesOf(A.class)));

您看到您的实现和Eclipse之间的区别的原因是您每次都扫描,而Eclipse(和其他工具)只扫描一次(大多数时候在项目加载期间)并创建索引。下次你请求数据时,它不再扫描,而是查看索引。

我只是写了一个简单的演示来使用org.reflections.Reflections来获取抽象类的子类:

https://github.com/xmeng1/ReflectionsDemo

在java中输入链接描述hereService Manager将获得J中接口的所有实现类

几年前我就这样做了。最可靠的方法(即使用官方Java api,没有外部依赖)是编写一个自定义doclet来生成一个可以在运行时读取的列表。

你可以像这样从命令行运行它:

javadoc -d build -doclet com.example.ObjectListDoclet -sourcepath java/src -subpackages com.example

或者像这样从ant运行它:

<javadoc sourcepath="${src}" packagenames="*" >
  <doclet name="com.example.ObjectListDoclet" path="${build}"/>
</javadoc>

下面是基本代码:

public final class ObjectListDoclet {
    public static final String TOP_CLASS_NAME =  "com.example.MyClass";        

    /** Doclet entry point. */
    public static boolean start(RootDoc root) throws Exception {
        try {
            ClassDoc topClassDoc = root.classNamed(TOP_CLASS_NAME);
            for (ClassDoc classDoc : root.classes()) {
                if (classDoc.subclassOf(topClassDoc)) {
                    System.out.println(classDoc);
                }
            }
            return true;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }
}

为了简单起见,我删除了命令行参数解析,并将其写入System。Out而不是file。