239 votes

Comment trouvez-vous toutes les sous-classes d’une classe donnée en Java ?

Comment aller à ce sujet et essayer de trouver toutes les sous-classes d'une classe donnée (ou tous les réalisateurs d'une interface donnée) en Java? Maintenant, j'ai une méthode pour faire cela, mais je trouve ça assez inefficace (pour dire le moins). La méthode est la suivante:

  1. Obtenir une liste de tous les noms de classe qui existent sur le chemin de classe
  2. Charge de chaque classe et de tester pour voir si c'est une sous-classe ou d'un réalisateur, de la classe ou de l'interface

Dans Eclipse, il y a une belle fonctionnalité appelée la Hiérarchie des types, qui parvient à montrer ce assez efficacement. Comment fait-on pour et de le faire par programmation?

151voto

fforw Points 2548

Balayage des classes n’est pas facile avec Java pur.

Le framework spring propose une classe appelée ClassPathScanningCandidateComponentProvider qui peut faire ce dont vous avez besoin. L’exemple suivant se trouverait toutes les sous-classes de MyClass dans le paquet org.example.package

Cette méthode a l’avantage supplémentaire d’utiliser un analyseur de bytecode pour trouver les candidats qui signifie qu’il seront pas charge toutes les classes il scanne.

80voto

matt b Points 73770

Il n'y a pas d'autre moyen de le faire, d'autres que ce que vous avez décrit. Pensez - y, comment peut-on savoir quelles classes d'étendre ClassX sans l'analyse de chaque classe sur le chemin de la classe?

Eclipse ne peux vous parler de la super et sous-classes dans ce qui semble être une "bonne" quantité de temps parce qu'il a déjà toutes les données de type chargé au point où vous appuyez sur la touche "Affichage dans la Hiérarchie de Type" bouton (car il est constamment en train de compiler vos classes, connaît tout sur le chemin de la classe, etc).

54voto

Mark Renouf Points 13128

Ce n'est pas possible de le faire en utilisant uniquement de l'intégré dans Java Réflexions de l'API.

Un projet qui ne la nécessaire, la numérisation et l'indexation de votre classpath de sorte que vous pouvez obtenir l'accès à cette information...

Réflexions

Un Java runtime analyse des métadonnées, dans l'esprit de Scannotations

Réflexions scanne votre classpath, les indices les métadonnées, vous permet de faire des requêtes sur le moteur d'exécution et peut enregistrer et de recueillir des informations pour de nombreux modules au sein de votre projet.

À l'aide de Réflexions vous pouvez interroger vos méta-données pour:

  • obtenez tous les sous-types d'un type de
  • obtenez tous les types annotés avec quelques annotations
  • obtenez tous les types annotés avec quelques annotations, y compris l'annotation des paramètres correspondant
  • obtenez toutes les méthodes annotées avec certains

(disclaimer: je n'ai pas utilisé, mais la description du projet semble être parfaitement adaptées à vos besoins.)

12voto

Rob Points 31432

N’oubliez pas que le généré Javadoc pour une classe comprendra une liste des sous-classes connues (et d’interfaces, connu et implémenter des classes).

9voto

Curtis Points 2157

Je sais que je suis quelques années de retard pour cette partie, mais je suis tombé sur cette question d'essayer de résoudre le même problème. Vous pouvez utiliser Eclipse interne de la recherche par programmation, si vous écrivez un Plugin Eclipse (et donc de profiter de leur mise en cache, etc), afin de trouver des classes qui implémentent une interface. Voici mon (très approximatif) la première coupe:

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

Le premier problème que je vois pour l'instant est que je suis le seul à en attraper des classes directement implémenter l'interface, pas tous les sous-classes - mais un peu de récursivité jamais fait de mal à personne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X