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

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

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


当前回答

除了你所描述的,没有别的办法了。想想看——如果不扫描类路径上的每个类,如何知道哪些类扩展了ClassX ?

Eclipse只能在看起来“有效”的时间内告诉您关于父类和子类的信息,因为在您按下“显示在类型层次结构中”按钮时,它已经加载了所有类型数据(因为它一直在编译您的类,知道类路径上的所有内容,等等)。

其他回答

我需要将此作为一个测试用例,以查看是否向代码中添加了新的类。这就是我所做的

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());
        }
    }
}

Try ClassGraph. (Disclaimer, I am the author). ClassGraph supports scanning for subclasses of a given class, either at runtime or at build time, but also much more. ClassGraph can build an abstract representation of the entire class graph (all classes, annotations, methods, method parameters, and fields) in memory, for all classes on the classpath, or for classes in selected packages, and you can query this class graph however you want. ClassGraph supports more classpath specification mechanisms and classloaders than any other scanner, and also works seamlessly with the new JPMS module system, so if you base your code on ClassGraph, your code will be maximally portable. See the API here.

除了你所描述的,没有别的办法了。想想看——如果不扫描类路径上的每个类,如何知道哪些类扩展了ClassX ?

Eclipse只能在看起来“有效”的时间内告诉您关于父类和子类的信息,因为在您按下“显示在类型层次结构中”按钮时,它已经加载了所有类型数据(因为它一直在编译您的类,知道类路径上的所有内容,等等)。

我知道我在这个派对上晚了几年,但我遇到这个问题是为了解决同样的问题。如果您正在编写Eclipse Plugin(从而利用它们的缓存等),您可以通过编程方式使用Eclipse的内部搜索来查找实现接口的类。这是我(非常粗糙的)第一次剪:

  protected void listImplementingClasses( String iface ) throws CoreException
  {
    final IJavaProject project = <get your project here>;
    try
    {
      final IType ifaceType = project.findType( iface );
      final SearchPattern ifacePattern = SearchPattern.createPattern( ifaceType, IJavaSearchConstants.IMPLEMENTORS );
      final IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
      final SearchEngine searchEngine = new SearchEngine();
      final LinkedList<SearchMatch> results = new LinkedList<SearchMatch>();
      searchEngine.search( ifacePattern, 
      new SearchParticipant[]{ SearchEngine.getDefaultSearchParticipant() }, scope, new SearchRequestor() {

        @Override
        public void acceptSearchMatch( SearchMatch match ) throws CoreException
        {
          results.add( match );
        }

      }, new IProgressMonitor() {

        @Override
        public void beginTask( String name, int totalWork )
        {
        }

        @Override
        public void done()
        {
          System.out.println( results );
        }

        @Override
        public void internalWorked( double work )
        {
        }

        @Override
        public boolean isCanceled()
        {
          return false;
        }

        @Override
        public void setCanceled( boolean value )
        {
        }

        @Override
        public void setTaskName( String name )
        {
        }

        @Override
        public void subTask( String name )
        {
        }

        @Override
        public void worked( int work )
        {
        }

      });

    } catch( JavaModelException e )
    {
      e.printStackTrace();
    }
  }

到目前为止,我看到的第一个问题是,我只捕获直接实现接口的类,而不是它们的所有子类——但一点递归不会伤害任何人。

你可以使用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)));