2009-12-18 14 views
62

Sto iniziando a programmare in Java e mi chiedo se esiste l'equivalente al C++ #define.#define in Java

Una rapida ricerca di Google dice che non è così, ma qualcuno potrebbe dirmi se esiste qualcosa di simile in Java? Sto cercando di rendere il mio codice più leggibile.

Invece di myArray[0] Desidero essere in grado di scrivere myArray[PROTEINS] ad esempio.

+8

Nel moderno C++ si dovrebbe usare una costante tipizzata piuttosto che una #define per quello –

+2

Sì, #define è in stile C. In C++ usa invece const. Vedi il libro "Effective C++" di Scott Meyers, voce 1. – Jabba

risposta

84

No, perché non esiste un precompilatore.

Tuttavia, tramite hotspot è abbastanza incredibilmente bravo a ottimizzare, ove possibile, così nel tuo caso si potrebbe ottenere la stessa cosa come segue:

class MyClass 
{ 
    private static final int PROTEINS = 0; 

    ... 

    MyArray[] foo = new MyArray[PROTEINS]; 

} 

Il compilatore noterà che PROTEINS può mai, mai cambiare e così sarà in linea esso che è più o meno quello che vuoi.

Nota che il modificatore di accesso sulla costante non è importante qui, quindi potrebbe essere public o protected anziché privato, se si desidera riutilizzare la stessa costante su più classi.

+13

Questo risponde alla domanda ma utilizza in modo improprio alcuni termini. Inline viene eseguito in fase di esecuzione quando il compilatore JIT rileva che un metodo è sia abbastanza semplice che non sovrascritto (non conosco tutte le regole e potrebbe cambiare da versione a versione). Una 'finale statica' di un tipo primitivo o String è definita dalla specifica del compilatore Java (non JIT) come una costante. Non è "in linea" nel senso di JIT, è in realtà direttamente compilato in quella parte del codice proprio come un #define è in C. –

5
static final int PROTEINS = 1 
... 
myArray[PROTEINS] 

Normalmente si inseriscono "costanti" nella classe stessa. E si noti che un compilatore può ottimizzare i riferimenti ad esso, quindi non cambiarlo a meno che non si ricompilino tutte le classi usando.

class Foo { 
    public static final int SIZE = 5; 

    public static int[] arr = new int[SIZE]; 
} 
class Bar { 
    int last = arr[Foo.SIZE - 1]; 
} 

Modifica ciclo ... SIZE=4. Compilare anche Bar perché il compilatore potrebbe aver appena scritto "4" nell'ultimo ciclo di compilazione!

4

Java non ha una direttiva preprocessore define generica.

Nel caso di costanti, si raccomanda di dichiarare come static finals, come in

private static final int PROTEINS = 100; 

Tali dichiarazioni sarebbero inline dai compilatori (se il valore è una costante di tempo di compilazione).

Si noti inoltre che i campi della costante finale statica pubblica fanno parte dell'interfaccia pubblica e che i loro valori non dovrebbero cambiare (come il compilatore li allinea). Se si modifica il valore, è necessario ricompilare tutte le origini che hanno fatto riferimento a tale campo costante.

+0

Bene, le finali statiche * private * non fanno realmente parte dell'interfaccia * public *. :) Per 'finali statiche pubbliche 'è vero, però. – Bombe

+0

@Mombe, corretto. L'ho scritto inizialmente come pubblico, ma poi cambiato senza aggiornare la risposta. – notnoop

34

Lo spazio dei commenti è troppo piccolo, quindi ecco alcune ulteriori informazioni sull'uso di static final. Come ho detto nel mio commento allo Andrzej's answer, solo le primitive e String sono compilate direttamente nel codice come valori letterali.Per dimostrare questo, provare quanto segue:

È possibile vedere in azione con la creazione di tre classi (in file separati):

public class DisplayValue { 
    private String value; 

    public DisplayValue(String value) { 
     this.value = value; 
    } 

    public String toString() { 
     return value; 
    } 
} 

public class Constants { 
    public static final int INT_VALUE = 0; 
    public static final DisplayValue VALUE = new DisplayValue("A"); 
} 

public class Test { 
    public static void main(String[] args) { 
     System.out.println("Int = " + Constants.INT_VALUE); 
     System.out.println("Value = " + Constants.VALUE); 
    } 
} 

compilare questi ed eseguire test, che stampa:

Int = 0 
Value = A 

Ora, modificare Constants per avere un valore diverso per ciascuna e compilare semplicemente la classe Constants. Quando si esegue nuovamente Test (senza ricompilare il file di classe) viene comunque stampato il vecchio valore per INT_VALUE ma non VALUE. Per esempio:

public class Constants { 
    public static final int INT_VALUE = 2; 
    public static final DisplayValue VALUE = new DisplayValue("X"); 
} 

Esegui test senza ricompilare Test.java:

Int = 0 
Value = X 

Nota che qualsiasi altro tipo utilizzato con static final è mantenuto come riferimento.

simili C/C++ #if/#endif, una costante letterale o una definita attraverso static final con primitive, utilizzato in un normale Java if condizione e valuta per false causerà il compilatore di spogliare il codice byte per le istruzioni all'interno del if blocco (non verranno generati).

private static final boolean DEBUG = false; 

if (DEBUG) { 
    ...code here... 
} 

Il codice di "... codice qui ..." non verrà compilato nel codice byte. Ma se hai cambiato DEBUG a true allora sarebbe.

+1

Sicuramente un +1 solo per lo sforzo! –

+0

Voglio solo aggiungere che java non fa lo stesso per 'enum's. –

0

La risposta più semplice è "Nessun metodo diretto per ottenerlo perché non esiste un pre-compilatore" Ma puoi farlo da solo. Utilizzare classi e quindi definire variabili come finale in modo che possa essere assunto come costante in tutto il programma
Non dimenticare di utilizzare finale e variabile come pubblico o protetto non privato altrimenti non sarà possibile accedervi da fuori classe

0

Più leggibile la soluzione utilizza Static Import. Quindi sarà non necessario utilizzare AnotherClass.constant.

Scrivere una classe con la costante come campo public static.

package ConstantPackage; 

public class Constant { 
    public static int PROTEINS = 1; 
} 

Poi basta utilizzare Statico Importa in cui è necessario il costante.

import static ConstantPackage.Constant.PROTEINS; 

public class StaticImportDemo { 

    public static void main(String[]args) { 

     int[] myArray = new int[5]; 
     myArray[PROTEINS] = 0; 

    } 
} 

sapere di più su Statico Importa vedere this stack overflow question.

2

C'è preprocessor for Java che fornisce direttive come #define, #ifdef, #ifndef e molti altri, ad esempio il team PostgresJDBC lo utilizza per generare fonti per casi diversi e per non duplicare codice.