如何在Java中找到给定类的所有子类(或给定接口的所有实现者)? 到目前为止,我有一个方法来做到这一点,但我发现它相当低效(至少可以说)。 方法是:
获取类路径上存在的所有类名的列表 加载每个类并测试它是否是所需类或接口的子类或实现者
在Eclipse中,有一个很好的特性叫做类型层次结构,它能够非常有效地显示这一点。 如何以编程的方式进行呢?
如何在Java中找到给定类的所有子类(或给定接口的所有实现者)? 到目前为止,我有一个方法来做到这一点,但我发现它相当低效(至少可以说)。 方法是:
获取类路径上存在的所有类名的列表 加载每个类并测试它是否是所需类或接口的子类或实现者
在Eclipse中,有一个很好的特性叫做类型层次结构,它能够非常有效地显示这一点。 如何以编程的方式进行呢?
当前回答
将它们添加到父类构造函数(this. getclass (). getname())内部的静态映射(或创建一个默认映射),但这将在运行时更新。如果可以选择延迟初始化,可以尝试这种方法。
其他回答
用纯Java扫描类并不容易。
spring框架提供了一个名为ClassPathScanningCandidateComponentProvider的类,它可以满足您的需要。下面的示例将在包org.example.package中找到MyClass的所有子类
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(MyClass.class));
// scan in org.example.package
Set<BeanDefinition> components = provider.findCandidateComponents("org/example/package");
for (BeanDefinition component : components)
{
Class cls = Class.forName(component.getBeanClassName());
// use class cls found
}
该方法还有一个额外的好处,就是使用字节码分析器来查找候选类,这意味着它不会加载所扫描的所有类。
您看到您的实现和Eclipse之间的区别的原因是您每次都扫描,而Eclipse(和其他工具)只扫描一次(大多数时候在项目加载期间)并创建索引。下次你请求数据时,它不再扫描,而是查看索引。
你可以使用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)));
我需要将此作为一个测试用例,以查看是否向代码中添加了新的类。这就是我所做的
final static File rootFolder = new File(SuperClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
private static ArrayList<String> files = new ArrayList<String>();
listFilesForFolder(rootFolder);
@Test(timeout = 1000)
public void testNumberOfSubclasses(){
ArrayList<String> listSubclasses = new ArrayList<>(files);
listSubclasses.removeIf(s -> !s.contains("Superclass.class"));
for(String subclass : listSubclasses){
System.out.println(subclass);
}
assertTrue("You did not create a new subclass!", listSubclasses.size() >1);
}
public static void listFilesForFolder(final File folder) {
for (final File fileEntry : folder.listFiles()) {
if (fileEntry.isDirectory()) {
listFilesForFolder(fileEntry);
} else {
files.add(fileEntry.getName().toString());
}
}
}
将它们添加到父类构造函数(this. getclass (). getname())内部的静态映射(或创建一个默认映射),但这将在运行时更新。如果可以选择延迟初始化,可以尝试这种方法。