2009-07-06 3 views
17

Eventuali duplicati:
How do you find all subclasses of a given class in Java?È possibile ottenere tutte le sottoclassi di una classe?

Ciao,

vorrei ottenere un elenco di classi che implementano un'interfaccia in Java in fase di esecuzione in modo da poter fare un servizio di ricerca, senza dover per codificarlo C'è un modo semplice per farlo? Non temo

+1

In C# è possibile eseguire questa operazione iterando attraverso la definizione di ogni classe in un assembly e testando ciascuna di queste classi per verificare se implementa tale interfaccia. – ChrisW

+3

Purtroppo, la domanda non riguarda C#. – Tom

+1

Duplicato? 'Come trovi tutte le sottoclassi di una determinata classe in Java?', Http://stackoverflow.com/questions/492184/how-do-you-find-all-subclasses-of-a-given-class-in- java – Jonik

risposta

24

La risposta breve è no.

La lunga risposta è che le sottoclassi possono nascere in molti modi, il che rende praticamente impossibile trovarle tutte categoricamente.

Non è possibile farlo in fase di esecuzione ma non è possibile trovare le classi fino a quando non vengono caricate e come si fa a sapere che vengono caricate? È possibile eseguire la scansione di ogni file JAR e di classe, ma non è definitivo. Inoltre ci sono cose come i caricatori di classe URL.

Le classi interne (statiche e non statiche) sono un altro caso da considerare. Le classi interne nominate sono più facili da trovare. Le classi interiori anonime sono potenzialmente molto più difficili da trovare.

Si deve anche considerare che se una classe ha sottoclassi, è possibile creare nuove sottoclassi in un secondo momento.

-2

Se si caricano solo le classi dal disco o dagli URL, è possibile eseguire la scansione del classpath e trovare le sottoclassi "manualmente".

0

Sto cercando di ragionare attraverso la risposta qui, quindi probabilmente ho torto. Non avrebbe senso che una classe abbia informazioni sui suoi discendenti o sottoclassi perché in qualsiasi momento qualcuno può creare una nuova sottoclasse della tua classe. Quindi dovresti ricompilare la tua classe per includere ogni volta queste nuove informazioni. Questo non ha senso per il codice estensibile. È più probabile che una classe contenga informazioni sui suoi antenati. Quindi l'unica soluzione che posso vedere è che tu possa scorrere tutte le classi nello spazio dei problemi e controllare, ma questa è probabilmente una soluzione orribile per te.

1

Posso sempre creare una nuova sottoclasse per qualsiasi classe non finale, aggiungere la sottoclasse al classpath e sconfiggere l'intenzione. La sottoclasse è una proposizione aperta.

Circa il meglio che puoi fare è dire che per un determinato percorso di classe, sai quali sono le sottoclassi, e per farlo, dovresti scansionare ogni classe nel classpath.

1

È piuttosto semplice utilizzare la riflessione. Leggi questo articolo da JavaWorld

http://www.javaworld.com/javaworld/javatips/jw-javatip113.html

+0

Ho letto male la domanda, l'articolo sopra è solo per trovare sottoclassi che implementano una determinata interfaccia –

+0

Questo codice scansiona solo un pacchetto particolare. Ma le sottoclassi potrebbero esistere in qualsiasi pacchetto. Nell'articolo si dice "siamo interessati a tutte le classi che implementano una determinata interfaccia, nessuna informazione disponibile è disponibile tramite Java Reflection". –

1

L'unico modo si sarebbe in grado di farlo è a piedi la gerarchia pacchetto per i pacchetti disponibili nel classpath controllare ogni classe attraverso la riflessione (e che è intenzione di succhiare perché si' caricherò in modo efficace ogni classe, a meno che non si limiti la ricerca a determinati pacchetti).

Il problema con questo tipo di comportamento auto-magico è che diventa difficile quantificare l'applicazione senza eseguirla, il che è un problema di manutenzione. Preferirei sempre seguire il percorso di iniezione (a-la Spring) passando le istanze tramite una sorta di configurazione.

0

Si desidera enumerare le classi che implementano una particolare interfaccia o enumerare le classi che derivano da qualche classe base? Questi sono due problemi diversi. Entrambi, per quanto ne so, sarebbero difficili da implementare, dal momento che nuove implementazioni possono essere create/installate su un PC in qualsiasi momento nel futuro. Sembra che tu stia cercando di creare un metodo factory per istanziare una particolare istanza e non vuoi hardcodificare il nome della classe nel codice. Solitamente l'uso di un file di configurazione che enumera tutte le classi che implementano l'interfaccia è la strada da percorrere (o un database può essere utilizzato). Man mano che le nuove classi implementano l'interfaccia, le aggiungi al file di configurazione e la factory deve prendere il nuovo nome della classe.

5

è necessario utilizzare Java ServiceLoader che è una classe integrata. È in grado di iterare in fase di runtime su tutte le implementazioni del servizio noto (interfaccia).

Se per qualche motivo non lo si desidera, è possibile utilizzare ClassLoader.getSystemResources() per eseguire un'iterazione su tutte le risorse; per esempio. se hai 6 volte il file /META-INF/com.interface otterrai 6 iterazioni.