2012-03-27 13 views
8

Ho una stringa con un certo valore. Voglio ripetere tutte le classi in un pacchetto chiamando un metodo specifico e se il valore restituito dal metodo è uguale al valore nella mia stringa, crea un oggetto di quella classe.È possibile iterare su tutte le classi all'interno di un pacchetto con Reflection?

Voglio farlo in modo dinamico, quindi se aggiungo una classe in questo pacchetto, sarà automaticamente nell'iterazione.

È possibile fare questo? Se no, c'è un modo per fare ciò che voglio?


Mi aspettavo qualcosa di simile.

for(Class clazz: SomeClass.listClasses("org.package")){ 
    //code here 
} 
+0

Che cosa significa "aggiungere una classe in questo pacchetto"? Come si ottiene nel classpath del processo java? –

+0

@Jeffrey Stavo leggendo su Reflection e penso che questo sia l'unico modo, ma non so nulla di Reflection. Ho provato un "modo normale" aggiungendo una verifica per ogni classe che ho in quel pacchetto, ma non voglio in questo modo perché non è espandibile. –

+0

@MiserableVariable In fase di sviluppo, aggiungo alcune nuove classi nel pacchetto (tutte le classi estendono una classe astratta chiamata Documento). –

risposta

8

No, questo non è possibile in modo totalmente affidabile; tuttavia, può essere pratico da implementare in molti casi.

A causa della flessibilità dei programmi di caricamento classe Java, le classi definite in un particolare pacchetto potrebbero non essere note in fase di esecuzione (ad esempio, considerare uno speciale classloader che definisce le classi al volo, magari caricandole dalla rete, o compilarli ad-hoc). Di conseguenza, non esiste un'API Java standard che consente di elencare le classi in un pacchetto.

In pratica, tuttavia, è possibile eseguire alcuni trucchi eseguendo una ricerca nel classpath per tutti i file di classe e JAR, creando una raccolta di nomi di classe completi e ricercandoli come desiderato. Questa strategia funzionerebbe bene se si è sicuri che nessun classloader attivo si comporterà come descritto nel paragrafo precedente. Ad esempio (pseudocodice Java):

Map<String, Set<String>> classesInPackage = new HashMap(); 
for (String entry : eachClasspathEntry()) { 
    if (isClassFile(entry)) { 
    String packageName = getPackageName(entry); 
    if (!classesInPackage.containsKey(packageName)) { 
     classesInPackage.put(packageName, new HashSet<String>()); 
    } 
    classesInPackage.get(packageName).add(getClassName(entry)); 
    } else if (isJarOrZipFile(entry)) { 
    // Do the same for each JAR/ZIP file entry... 
    } 
} 
classesInPackage.get("com.foo.bar"); // => Set<String> of each class... 
+0

Ma un classloader personalizzato potrebbe, almeno in teoria. –

+0

@MiserableVariable: immagina di aver scritto un classloader personalizzato che implementa il metodo 'defineClass (String)' restituendo il bytecode per una classe che definisce una classe vuota in base al nome della classe data. Questo è un classloader totalmente valido e non esiste un modo (pratico) di elencare ogni classe che potrebbe definire. – maerics

+0

Sì, in generale il problema non è risolvibile. Ma è diverso per specifiche situazioni strette - potrei voler controllare tutti i file .class in un nome di cartella 'plugins' e creare un'istanza su ogni classe che abbia un metodo' register'. –

1

Sì, ma non come soluzione generale. Dovrai impacchettare il tuo codice e invocare la JVM in modo specifico. In particolare, dovrai creare un agente Instrumentation e chiamare java.lang.instrument.Instrumentation.getAllLoadedClasses().

Il pacchetto documentation for java.lang.instrument contiene molti dettagli su come creare e creare un'istanza di un agente.

+0

Non vuole solo le classi caricate, ma (presumibilmente) tutti i nuovi file di classe rilasciati in una cartella in classpath –

+0

@MiserableVariable Non so se è chiaro, ma le classi che voglio caricare sono definite in Tempo di sviluppo, non in runtime. –

2

Posso pensare a due modi per risolvere quello che penso sia il tuo problema, anche se né iterare veramente su tutte le classi in un pacchetto.

Uno consiste nel creare un file separato che elenca le classi su cui deve essere chiamato quel metodo specifico. Questo è abbastanza facile da implementare. Potresti avere un po 'di lavoro nel creare il file, ma questo potrebbe essere automatizzato.

La seconda opzione consiste nel cercare i file .class in un posto ben noto, ad esempio una singola cartella o un set di cartelle, e indovinare il nome della classe e caricarlo. Se questo è un processo di sviluppo semplice, i file di classe da un singolo pacchetto sono probabilmente in una singola directory.

Problemi correlati