如何在Java中找到给定类的所有子类(或给定接口的所有实现者)? 到目前为止,我有一个方法来做到这一点,但我发现它相当低效(至少可以说)。 方法是:
获取类路径上存在的所有类名的列表 加载每个类并测试它是否是所需类或接口的子类或实现者
在Eclipse中,有一个很好的特性叫做类型层次结构,它能够非常有效地显示这一点。 如何以编程的方式进行呢?
如何在Java中找到给定类的所有子类(或给定接口的所有实现者)? 到目前为止,我有一个方法来做到这一点,但我发现它相当低效(至少可以说)。 方法是:
获取类路径上存在的所有类名的列表 加载每个类并测试它是否是所需类或接口的子类或实现者
在Eclipse中,有一个很好的特性叫做类型层次结构,它能够非常有效地显示这一点。 如何以编程的方式进行呢?
当前回答
仅使用内置的Java Reflections API是不可能做到这一点的。
存在一个项目,它对你的类路径进行必要的扫描和索引,这样你就可以访问这些信息……
反射
Java运行时元数据分析,遵循Scannotations的精神 Reflections扫描您的类路径,索引元数据,允许您在运行时查询它,并可以为项目中的许多模块保存和收集这些信息。 使用Reflections你可以查询你的元数据: 获取某个类型的所有子类型 用一些注释来注释所有类型 获取使用某些注释注释的所有类型,包括注释参数匹配 让所有方法都带有一些注解
(免责声明:我没有使用过它,但项目的描述似乎完全符合您的需求。)
其他回答
几年前我就这样做了。最可靠的方法(即使用官方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。
记住其他答案中提到的限制,你也可以以以下方式使用openpojo的PojoClassFactory(在Maven上可用):
for(PojoClass pojoClass : PojoClassFactory.enumerateClassesByExtendingType(packageRoot, Superclass.class, null)) {
System.out.println(pojoClass.getClazz());
}
packageRoot是你想要搜索的包的根字符串。“com。mycompany”或者只是“com”),超类是你的超类型(这也适用于接口)。
你可以使用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)));
不要忘记,为类生成的Javadoc将包括一个已知子类列表(对于接口,包括已知实现类)。
将它们添加到父类构造函数(this. getclass (). getname())内部的静态映射(或创建一个默认映射),但这将在运行时更新。如果可以选择延迟初始化,可以尝试这种方法。