2012-03-24 17 views

risposta

6

La risposta è No. Non nel senso che intendi.

Il modo di fare questo genere di cose in Java come segue:

private static final boolean flag = true; /* or false :-) */ 

if (flag) { 
    /* code */ 
} else { 
    /* different code */ 
} 

Java non ha un preprocessore (come C e C++ fanno). Tuttavia, il compilatore ottimizzerà il ramo non utilizzato di una dichiarazione if come sopra, FORNITO che flag è un'espressione costante in fase di compilazione. Questa è una forma limitata di compilazione condizionale. Si noti che la costante di controllo flag può essere importata da una classe diversa.

(IIRC, è specificato questo comportamento nel JLS ... che significa che si può fare affidamento su qualsiasi compilatore Java conforme a farlo.)


commenti @Treebranch che "questo" può causare il codice gonfiare.

  1. Se @Treebranch sta parlando di codice oggetto gonfiato, questo non è vero. Se lo fai correttamente con flag/espressioni che sono espressioni costanti in fase di compilazione come definite dal JLS, il compilatore non emetterà alcun bytecode per il codice sorgente "condizionalmente escluso". Vedi la risposta di @ edalorso.

  2. Se @Treebranch sta parlando di codice sorgente, sono d'accordo. Ma puoi dire la stessa cosa per la compilazione condizionale #ifdef. (Macro e #include possono essere usati per ridurre il bloat del codice sorgente ... ma solo a costo di leggibilità, manutenibilità, ecc. E questa era la ragione per cui i progettisti Java si rifiutavano di supportare qualsiasi pre-elaborazione del codice sorgente.)

  3. Java ha un modo migliore di gestire le differenze di piattaforma, le variazioni di funzionalità e così via: utilizzare il binding dinamico . Se avere un sacco di diverse classi di plug-in nel proprio JAR è un problema (bytecode bloat), gestirlo creando un file JAR diverso per ogni piattaforma o altro.

+0

L'OP ha chiesto "c'è un modo per farlo in java? * (Che non sta definendo una variabile statica globale ..) *" –

+0

Java non ha variabili globali ... quindi tecnicamente quel pilota è discutibile. –

+0

Si potrebbe sostenere che i campi 'static final' sono l'equivalente delle variabili globali in es. C++ (almeno dal punto di vista dell'utilizzo) ... ma la tua interpretazione è confermata dall'accettazione dell'OP, quindi ottieni anche il mio +1 :-) –

0

Lo snippato sopra è stato un conditional compilation macro destinato al preprocessore che "trasforma" il codice sorgente prima della compilazione.

Java non ha il costrutto linguaggio equivalente, quindi l'anser è impossibile farlo.

Edit: Si può fare comunque utilizzare condizioni regolari per raggiungere il tuo obiettivo, dal momento che in questo modo il compilatore di ottimizzare il bytecode in modo tale, se lo desideri (grazie per @StephenC per la precisazione).

Ma personalmente preferisco estendere l'API per il debug, laddove necessario, che nasconderà i dettagli di implementazione e può essere modificato in runtime. Naturalmente questo è specifico dello scenario.

Ad esempio questo sarebbe simile a Log4j-s API, che consente di verificare se il codice è in modalità di debug o meno.

Vorrei raccomandare l'uso di questo modello perché ciò non infrange (troppo :) i nostri amati concetti orientati agli oggetti.

+0

* "Tuttavia, è possibile utilizzare condizioni normali per raggiungere l'obiettivo, ma ciò non influirà sul processo di costruzione a seconda del token." * - Non strettamente vero. Se la condizione è un'espressione costante in fase di compilazione, il codice viene letteralmente rimosso al momento della compilazione. –

+0

Sì, è vero, ma contrariamente a C/C++ in cui le macro del preprocessore indicano esplicitamente quali parti tagliare, in Java la meccanica che hai descritto è implicita, quindi non visibile dal codice sorgente. – xea

+0

1) È ** ** visibile nel codice sorgente. Tutto quello che devi fare è ** guardare ** per i flag delle costanti in fase di compilazione e dove vengono utilizzati. OK, non spicca come un pollice irritato ... come '# ifdef' fa. 2) Dovresti correggere il misteringment che ho indicato e che (penso) tu riconosca –

0

Non c'è niente come la compilazione condizionale in Java. (come ha detto xea)

A seconda del problema che si desidera risolvere ci sono vari modi per fare qualcosa di simile.

Uno consiste nell'utilizzare una variabile finale statica impostata su una costante di tempo di compilazione (come scrive Stephen). Il compilatore in realtà non include il codice byte per il percorso impossibile. Ma deve ancora essere java legale, il che significa che non è possibile dichiarare una variabile in uno di questi blocchi e usarla in un altro.

Tutti i casi che ho visto fino ad ora si possono risolvere usando i costrutti OO. Ad esempio, puoi sostituire il tuo if else con una chiamata a un metodo astratto e fornire un debug e un'implementazione di produzione.

0

Java come linguaggio non ha pre-elaborazione o macro come C o C++ simile, tuttavia, ci sono some3rd partypreprocessor -tools, in grado di gestire le cose come queste. Per un utilizzo pratico, è necessario collegarli in una build Maven o Ant.

0

Penso che quello che @StephenC ha proposto sia una buona opzione. In alternativa, puoi provare a utilizzare AspectJ per tessere il codice che desideri per una particolare implementazione. È quindi possibile semplicemente rimuovere l'aspetto (non tessere nel codice) quando non lo si desidera come parte dell'implementazione. AspectJ modifica il bytecode (codice Java compilato) in base ai tipi di posizioni (chiamati pointcuts) specificati. Questo è particolarmente adatto per cose come aggiungere la registrazione al tuo programma.

Se questo è un approccio che ti interessa, controlla: AspectJ e Reference Guide.

+0

AspectJ è in effetti una lingua diversa ... –

+0

Sarei d'accordo ... tuttavia, è un approccio che l'OP deve prendere in considerazione. Alla fine tutto viene compilato in bytecode. – jbranchaud

4

L'approccio che suggerisce che l'utilizzo della variabile booleana statica finale è il più vicino a quella caratteristica suggerita perché è addirittura ottimizzato dal compilatore. Se il flag è impostato su false, i bytecode contenuti nel blocco non vengono nemmeno generati.

Mi permetta di mostrare un esempio:

public class Optimized { 

    private static final boolean DEBUG = true; 

    public static void main(String[] args) { 
     if(DEBUG){ 
      System.out.println("DEBUG enabled"); 
     } 
    } 

} 

Questo genera il bytecode

public class Optimized { 
    public Optimized(); 
    Code: 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return 

    public static void main(java.lang.String[]); 
    Code: 
     0: getstatic  #2     // Field java/lang/System.out:Ljava/io/PrintStream; 
     3: ldc   #3     // String DEBUG enabled 
     5: invokevirtual #4     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
     8: return 
} 

Ma se ci rivolgiamo la bandiera fuori ...

private static final boolean DEBUG = false; 

I bytecode guardano come segue

public class Optimized { 
    public Optimized(); 
    Code: 
     0: aload_0 
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return 

    public static void main(java.lang.String[]); 
    Code: 
     0: return 
} 

Quindi, AFAIK, questo è il più vicino possibile ottenere una direttiva di precompilazione in Java.

+0

+1 per esplicito –

Problemi correlati