2009-12-17 20 views
20

Sono un programmatore C++ di lunga data, nuovo in Java. Sto sviluppando un progetto Java Blackberry in Eclipse. Domanda: c'è un modo per introdurre diversi set di configurazione all'interno del progetto e quindi compilare un codice leggermente diverso in base a quelli?Compilazione Java condizionale

In Visual Studio, abbiamo configurazioni di progetto e #ifdef; So che non c'è #ifdef in Java, ma forse qualcosa a livello di file?

+2

Se sei solo preoccupato per quello che accade nel vostro file jar (ad esempio, la produzione, non sviluppo), il tuo sistema di compilazione (ad esempio, Ant) è il luogo in cui puoi controllare quali file vengono creati. – jdigital

+0

Grazie a tutti, vedo. La compilazione condizionale (sorta di) è abbastanza facile, ma apparentemente non esiste alcun supporto nativo per più target in un progetto in Eclipse. Andrò a leggere su Ant. –

risposta

3

No, Java non ha una corrispondenza esatta per tale funzionalità. È possibile utilizzare gli aspetti o utilizzare un contenitore IOC per iniettare classi di implementazione diverse.

+0

+1 per menzionare la classe di implementazione – extraneon

1

È possibile utilizzare il filtro delle risorse di maven in combinazione con i campi finali statici pubblici, che verranno effettivamente compilati in modo condizionale.

private static final int MODE = ${mode}; 

... 

if (MODE == ANDROID) { 
    //android specific code here 
} else { 

} 

Ora è necessario aggiungere una proprietà alla pom Maven "modalità", che dovrebbe essere dello stesso valore come il vostro costante Android.

Il compilatore java dovrebbe (!) Rimuovere il blocco if e else, lasciando così il proprio codice Android.

Non testet, quindi non c'è garanzia e preferisco la configurazione invece della compilazione condizionale.

+3

Questo non è davvero adatto per quantità significative di codice. Java ha interfacce, implementazioni ed ereditarietà per questo tipo di problemi. – extraneon

+0

concordato. Questo è il motivo per cui ho detto che preferirei la configurazione. – whiskeysierra

1

È possibile integrare m4 nel processo di compilazione per legare in modo efficace un analogo al preprocessore C davanti al compilatore Java. Molto movimento manuale si trova nel passaggio "integrazione", ma m4 è la tecnologia giusta per il processo di elaborazione del testo.

+2

Java ha altre risposte agli stessi problemi. Se devi armeggiare con i file per questo tipo di problemi più comuni, stai davvero facendo qualcosa di sbagliato nel design. – extraneon

+1

Nota la richiesta dell'OP: * [I] c'è un modo per introdurre diversi set di configurazione all'interno del progetto e quindi compilare un codice leggermente diverso in base a quelli? * Per "compilare un codice leggermente diverso", si deve alimentare un codice sorgente diverso al compilatore . Sì, ho letto del trucco booleano finale statico, ma non penso che questo fosse ciò che l'OP stava cercando. – seh

0

in Eclipse si può usare più progetti

  • principale (contiene il codice comune)
  • Version1 (contiene codice version1)
  • Version2 (contiene il codice Version2)

    1. principale - > Seleziona Progetto-> Proprietà-> Percorso build Java-> scheda Progetti
    2. Seleziona Aggiungi ...
    3. Aggiungere "Version1" xor "Versione2" e OK di nuovo nell'area di lavoro.

Version1 e la versione due contengono gli stessi file, ma diverse implementazioni. In Main normalmente scrivi ad es.

import org.mycustom.Version; 

E se hai incluso progetto Version1/Version2 come riferimento si compilerà con il file Version.java dal progetto Version1/Version2.

+0

Ma non avresti bisogno di mantenere più copie del codice sorgente con solo le parti selezionate che differiscono? – Pacerier

14

È possibile impostare i campi 'finali' e if per far sì che il compilatore ottimizzi i codici byte compilati.

... 
public static final boolean myFinalVar=false; 
... 
if (myFinalVar) { 
do something .... 
.... 
} 

Se 'myFinalVar' è falso quando il codice viene compilato il bit 'fare qualcosa ....' sarà perso della classe compilato. Se si dispone di più di una condizione, è possibile riordinarle un po ': spostarle tutte in un'altra classe (ad esempio "Config.myFinalVar") e quindi è possibile mantenere tutte le condizioni in un posto pulito.

Questo meccanismo è descritto in 'Hardcore Java'.

[In realtà penso che questo è lo stesso meccanismo "ifdef poveri" la postato in precedenza.]

+0

Hai dimenticato di rendere effettivamente la variabile finale .... – Erhannis

+1

Hardcore Java critique http://programmers.stackexchange.com/a/7049/24257 .... – Pacerier

+0

@Pacerier - grazie per il collegamento - come Per la critica ho anche scoperto che l'edizione del libro che ho comprato aveva diversi problemi che dovevano essere corretti (alcuni esempi di codice, ad esempio, erano "fuori ordine") - e penso che sia una buona gente che dovrebbe vedere il libro critica - ma voglio solo far notare a chiunque stia leggendo questo post che il meccanismo specifico descritto sulla 'compilazione condizionale' (come in molti dei libri) è ancora valido. – monojohnny

6

è possibile gestire classpath diverso, ad esempio, realizzare ogni ' Azione' in una serie di directory distinte:

dir1/Main.java 
dir2/Action.java 
dir3/Action.java 

quindi utilizzare un percorso di classe diversa per ogni versione

javac -sourcepath dir1 -cp dir2 dir1/Main.java 

o

javac -sourcepath dir1 -cp dir3 dir1/Main.java 
+0

Ma questo non significa che dobbiamo mantenere più copie del codice sorgente? – Pacerier

+0

no, solo la parte condizionale. Ho scritto questo 5 anni fa. Vorrei usare una buona 'vecchia' se 'affermazione ora. – Pierre

+0

Hm, ma per far funzionare tutto ciò, la parte condizionale deve essere mescolata con il codice sorgente, quindi avremmo effettivamente due copie del codice sorgente? – Pacerier

5

In JDK6, è possibile farlo utilizzando l'interfaccia ServiceLoader di Java. Controllalo here.

+0

questa è una caratteristica interessante di cui non avevo mai sentito parlare fino ad ora. – Joel

+1

questo non è davvero così famoso a causa del fatto che molti attori dominanti sono presenti nel mercato open source. Ma l'ho trovato estremamente utile considerando il fatto che non si desidera utilizzare contenitori IOC in piena regola e si desidera caricare diverse implementazioni della stessa interfaccia. – Shamik

+1

Non funzionerà per lui poiché il suo obiettivo è BlackBerry, che è J2ME. –

1

Oltre a Maven, Ant e altri strumenti di build che forniscono funzionalità simili, uno preferirebbe creare interfacce in Java e passare le implementazioni in Runtime.
Vedere la Strategy Pattern per maggiori dettagli

In opposta a C/C++ questo non sarà disponibile con un grande penalità prestazioni, come Javas JIT-compilatore ottimizza in fase di esecuzione ed è in grado di inline questo pattern nella maggior parte dei casi.
Il grande vantaggio di questo modello è la flessibilità: è possibile modificare l'implementazione sottostante senza toccare le classi principali.

È inoltre necessario controllare IoC e Observer Pattern per ulteriori dettagli.

5

Se si desidera che questo appositamente per BlackBerry, il BlackBerry JDE ha a pre-processor:

È possibile attivare la pre-elaborazione per le applicazioni aggiornando il file di configurazione di Eclipse ™ .

In C: \ Program Files \ Eclipse \ configurazione \ config.ini, aggiungere la seguente riga: osgi.framework.extensions = net.rim.eide.preprocessing.hook Se si attiva la pre-elaborazione dopo aver hanno avuto una build, è necessario pulire il progetto dal menu Progetto prima di si compila nuovamente il progetto.

Poi si può fare le cose nel codice come:

//#ifdef SOMETHING 
// do something here 
//#else 
// do something else 
//#endif 

Per i dettagli si veda Specifying preprocessor defines

+0

l'url ha fatto fallire, forse era questo: http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/1407892/How_To_-_Use_the_preprocessor.html?nodeid=1487658&vernum=0 - http://rzr.online.fr/q/preprocessor – RzR

+1

Gli URL devono essere cambiati. Ho aggiornato i collegamenti. –

Problemi correlati