2010-07-22 12 views
8

ho una funzionalità che desidero fornire ad un cliente per un mockup software che stiamo preparando - e voglio sapere se èTrovare nuova classe Java a runtime

  1. possibile
  2. intelligente (aka non stupido)
  3. la cosa migliore

voglio che il cliente sia in grado di scrivere una classe Java che implementa la mia interfaccia Computable e incollarla in qualche cartella predeterminato. Questa cartella conterrà i file .java piuttosto che i file .class. Quindi, durante il runtime, voglio che il mio programma cerchi tale cartella ed estrae tutto il Computables da quella cartella e li memorizzi in una mappa dal nome dello Computable all'oggetto Computable. Lo Computable dovrebbe avere solo un costruttore predefinito e l'interfaccia avrà solo un metodo chiamato compute che mappa un array di Object in un Object.

+0

Si desidera compilare i file degli utenti in fase di runtime? – jedierikb

+0

Deve essere la lingua stessa o un altro linguaggio di scripting va bene? – skaffman

+0

@jedierikb Se è abbastanza facile da compilare in fase di runtime, andrebbe bene. Non voglio che il cliente debba preoccuparsi di trascinare i file di classe. – JnBrymn

risposta

9

Il Java Compiler API introdotto in Java SE 6 dovrebbe darti quello che ti serve.

+0

Si noti che questa API è disponibile solo in JDK, non in JRE. Quindi, se hai intenzione di distribuirlo, l'utente finale/client deve aver installato JDK e questo è piuttosto raro tra il grande pubblico. – BalusC

+0

Ouch! Grazie a @BalusC. – djna

+0

@BalusC La 'x' alla fine di javax implica sempre questo? – JnBrymn

0
+0

Sembra promettente, ma sembra ruotare attorno a due possibili soluzioni. 1) Usa un'API un ragazzo costruito per se stesso (non voglio rischiare di giocare con il framework di qualcun altro nel breve lasso di tempo che ho lasciato.) O 2) Usare il reflection per capire quali classi già caricate implementano 'Computable'. Ricorda che le mie classi non verranno caricate ... sono solo file .java. – JnBrymn

0

ho che questo sarebbe più semplice se hai permesso al cliente di digitare una dichiarazione di codice utilizzando qualcosa come Groovy, che è abbastanza Java-ish, e facile da eseguire in fase di esecuzione da un valore di stringa.

+0

Non è Groovy un superset rigido? Se è così, suppongo che potresti semplicemente dire al tuo cliente che sta prendendo Java e che non saranno più saggi. –

+0

Ah, ho sbagliato. Un file java è quasi sempre un codice groovy valido, ma non è un superset rigido. –

1

Se è abbastanza facile da compilare in fase di esecuzione, ciò andrebbe bene.

È possibile utilizzare javax.tools per eseguire la compilazione in base alle esigenze. Create dynamic applications with javax.tools può essere d'aiuto. È anche possibile farlo in memory.

Un avvertimento: l'uso del compilatore crea una dipendenza dal JDK; il solo JRE è insufficiente.

+0

Hai qualche codice di esempio? Devo indirizzare la riga di comando da Java per eseguire javac? Come penso di risucchiare il file di classe e costruire la classe? – JnBrymn

+0

@John Berryman: Ho aggiunto un link sopra. – trashgod

0

E 'abbastanza facile per scorrere l'elenco dei file in una cartella. Qualcuno ha detto che è possibile chiamare il compilatore Java da Java (se si ridistribuisce il JDK, che penso sia un punto la cui legalità deve essere controllata !!) Questa è una parte della battaglia.

Sembra che tu abbia un modello fisso nella tua mente in cui solo i file che soddisfano una determinata interfaccia vengono estratti dalla cartella. Penso che questo sia il posto dove il tuo metodo deve dare un po '. Il modo ragionevole (IMO) per fare ciò sarebbe compilare tutti i file in quella cartella, e poi con le loro classi nascoste da qualche parte, è possibile caricarle e rifletterle e quindi determinare quale di esse "fa" l'interfaccia e quali don 't. Quelle che non saranno state caricate inutilmente nella tua JVM, ma a meno che non siano intenzionalmente molto sprecate nello spazio, il codice che non esegui non può danneggiare il tuo programma.

Dopo aver determinato quali sono le cose computabili, è possibile memorizzare le classi (o le relative istanze) in una raccolta e fare ciò che si desidera con esse. Semplicemente ignori gli altri.

3

È possibile trovare Google Reflections utile per trovare le classi che implementano/estendono una determinata interfaccia/superclasse nel classpath. E 'poi così semplice come

Reflections reflections = new Reflections("my.project.prefix"); 
Set<Class<? extends SomeClassOrInterface>> subTypes = reflections.getSubTypesOf(SomeClassOrInterface.class); 

Poi, per verificare se si ha infatti un costruttore di default no-arg, basta controllare per ogni se Class#newInstance() non gettare alcuna eccezione.

+0

E se il file .class non si trovasse sul percorso corrente, ma in una cartella che apprendiamo solo in fase di esecuzione? – JnBrymn

+1

È possibile aggiungere percorsi al classpath durante il runtime utilizzando ['URLClassLoader'] (http://java.sun.com/javase/6/docs/api/java/net/URLClassLoader.html). – BalusC

0

È possibile utilizzare BeanShell. Questa libreria è piccola e non richiede il JDK. È usato in un numero di IDE e server web. L'ultima versione sembra avere il supporto necessario per caricare i file .java dal percorso della classe. (Ancora in beta)

Problemi correlati