2013-05-27 3 views
18

Questo è molto diffuso codice enum singoletto:Singleton via enum way è pigro inizializzato?

public enum enumClazz{ 
    INSTANCE 
    enumClazz(){ 
    //do something 
    } 
} 

e un mazzo di posti detto che è un inizializzazione ritardata. Ma io sono confuso dopo aver letto il capitolo 7 della 'Inside the Java Virtual Machine' - la durata di una Tipo:

La specifica Java virtual machine dà implementazioni flessibilità nella tempistica di classe e l'interfaccia di caricamento e il collegamento, ma rigorosamente definisce i tempi di inizializzazione. Tutte le implementazioni devono inizializzare ogni classe o interfaccia al primo utilizzo attivo. Sei situazioni seguenti qualificano usi attive:

  • viene creata una nuova istanza di una classe (in bytecode, l'esecuzione di una nuova istruzione alternativa, tramite la creazione implicita, riflessione, clonazione o deserializzazione..)
  • l'invocazione di un metodo statico dichiarata da una classe (in bytecode, l'esecuzione di un'istruzione invokestatic)
  • l'uso o cessione di un campo statico dichiarata da una classe o interfaccia, tranne per i campi statici che sono finale e inizializzato da un'espressione costante in fase di compilazione (in bytecode s, l'esecuzione di un getstatic o istruzione putstatic)
  • L'invocazione di taluni metodi riflettenti API Java, come i metodi della classe classe o delle classi nel java.lang.reflect pacchetto
  • L'inizializzazione di una sottoclasse di una classe (inizializzazione di una classe richiede prima inizializzazione della sua superclasse.)
  • la designazione di una classe come classe iniziale (con la principale < metodo()) quando una macchina virtuale Java avvia

Il terzo punto con stile grassetto chiarisce che se il campo è static final, l'inizializzazione del campo è avvenuta in fase di compilazione. Allo stesso modo, INSTANCE in enumClazz è implicitamente uguale a public static final e conforme al terzo punto.

Qualcuno può correggermi se la mia comprensione è sbagliata?

risposta

25

enum campi di istanza sono non "inizializzato da un'espressione costante in fase di compilazione". Loro non possono essere, perché only String and primitive types are possible types for a compile-time constant expression.

Ciò significa che la classe verrà inizializzata quando si accede per la prima volta a INSTANCE (che è esattamente l'effetto desiderato).

L'eccezione nel grassetto sopra esiste, perché queste costanti (static final campi inizializzati con una fase di compilazione espressione costante) siano effettivamente inline durante la compilazione:

class A { 
    public static final String FOO = "foo"; 

    static { 
    System.out.println("initializing A"); 
    } 
} 

class B { 
    public static void main(String[] args) { 
    System.out.println(A.FOO); 
    } 
} 

Esecuzione classe B in questo esempio non inizializzare A (e sarà non stampare "inizializzazione A"). E se guardi nel bytecode generato per B vedrai una stringa letterale con il valore "pippo" e no riferimento alla classe A.

3

Il terzo punto con stile audace chiarire che se il campo è 'static final', l'initialzation del campo è accaduto al complie tempo

Non esattamente - si applica solo ai "statica campi che sono finali e inizializzato da una fase di compilazione espressione costante ":

static final String = "abc"; //compile time constant 
static final Object = new Object(); //initialised at runtime 

Nel tuo caso, il singleton saranno inizializzare d quando viene caricata la classe enum, ovvero la prima volta che viene fatto riferimento al codice enumClazz.

Così è effettivamente pigro, a meno che non si dispone di una dichiarazione da qualche parte in voi codice come questo, per esempio, che avrebbe inutilmente inizializzare il tuo Singleton come parte del processo di caricamento delle classi:

Class<?> c = enumClazz.class; 
+0

class Singleton {public static final instance = new Singleton(); ...} Quindi, per la classe generica, questa 'instance' è pigra inizializzata? –

+0

Sì, sarebbe inizializzato pigramente allo stesso modo. – assylias

+0

Tutto azzerato. Grazie mille :) –