2012-08-02 9 views
8

Questo è da Effective Java:ordine di esecuzione dei blocchi statici in un tipo di WRT Enum al costruttore

// Implementing a fromString method on an enum type 
    private static final Map<String, Operation> stringToEnum 
     = new HashMap<String, Operation>(); 

    static { // Initialize map from constant name to enum constant 
    for (Operation op : values()) 
     stringToEnum.put(op.toString(), op); 
    } 

    // Returns Operation for string, or null if string is invalid 
    public static Operation fromString(String symbol) { 
    return stringToEnum.get(symbol); 
    } 

Si noti che le costanti di funzionamento sono messi in mappa stringToEnum da un blocco statico che viene eseguito dopo le costanti sono state create. Provare a rendere ogni costante inserita nella mappa dal proprio costruttore causerebbe un errore di compilazione. Questa è una buona cosa, perché causerebbe una NullPointerException se fosse legale. I costruttori Enum non sono autorizzati ad accedere ai campi statici dell'enum, eccetto per i campi delle costanti in fase di compilazione. Questa restrizione è necessaria perché questi campi statici non sono stati ancora inizializzati quando i costruttori sono in esecuzione.

La mia domanda è per quanto riguarda la linea:

"Si noti che le costanti di funzionamento sono messi in mappa stringToEnum da un blocco statico che viene eseguito dopo le costanti sono stati creati".

Ho pensato che il blocco statico venga eseguito prima dell'esecuzione del costruttore. Vengono effettivamente eseguiti durante il tempo di caricamento della classe.

Cosa mi manca qui?

+0

Vedi http://stackoverflow.com/questions/3028219/are-there-any-guarantees-in-jls-about-order-of-execution-static -inizializzazione-b –

risposta

11

Capisco la tua domanda come: perché c'è una garanzia che le costanti enum verranno inizializzate prima che il blocco statico venga eseguito. La risposta è data nel JLS, e un esempio specifico è riportata #8.9.2.1, con la seguente spiegazione:

inizializzazione statico avviene dall'alto verso il basso.

e le costanti di enumerazione sono implicitamente statiche finali e vengono dichiarate prima del blocco di inizializzazione statico.

EDIT

il comportamento non è diverso da una classe normale. Il codice qui sotto stampe:

In constructor: PLUS 
PLUS == null MINUS == null 

In constructor: MINUS 
PLUS != null MINUS == null 

In static initialiser 
PLUS != null MINUS != null 

In constructor: after static 
PLUS != null MINUS != null 
public class Operation { 

    private final static Operation PLUS = new Operation("PLUS"); 
    private final static Operation MINUS = new Operation("MINUS"); 

    static { 
     System.out.println("In static initialiser"); 
     System.out.print("PLUS = " + PLUS); 
     System.out.println("\tMINUS = " + MINUS); 
    } 

    public Operation(String s) { 
     System.out.println("In constructor: " + s); 
     System.out.print("PLUS = " + PLUS); 
     System.out.println("\tMINUS = " + MINUS); 
    } 

    public static void main(String[] args) { 
     Operation afterStatic = new Operation ("after static"); 
    }  
} 
+0

dice che l'Operazione rappresenta l'operazione di un calcolatore. E le costanti (PLUS, MINUS, DIVIDE, MULTIPLY) verranno create solo dopo l'esecuzione del costruttore. Quindi sono confuso su come le costanti possono essere inizializzate prima dell'esecuzione del costruttore.I campi finali statici impliciti che contengono le costanti possono essere creati prima del costruttore, ma possono essere assegnati solo dopo l'esecuzione del costruttore. – Geek

+1

ogni costante (PLUS, MINUS ...) verrà inizializzata dopo l'esecuzione del rispettivo costruttore. L'ordine di esecuzione, se lo desideri, sarà: 'PLUS = nuova operazione (...); MINUS = new Operation (...); ...; static block' – assylias

+0

Ecco perché Bloch dice che se si tenta di popolare la mappa dai costruttori perché le costanti non sono state inizializzate fino a quando tutti i costruttori non hanno finito di funzionare. – assylias

0

Operation le costanti sono campi statici creati nel blocco statico nell'ordine di visualizzazione.

static { 
    // instantiate enum instances here 
    ... 
    // Initialize map from constant name to enum constant  
    for (Operation op : values())  
     stringToEnum.put(op.toString(), op); 
} 
0

I static blocchi eseguire in ordine di apparizione (è possibile avere blocchi statici multipli), quando il caricatore di classe carica della classe, per esempio. funziona prima del costruttore.

Problemi correlati