2014-10-09 16 views
116

Ho letto che è possibile implementare Singleton in Java utilizzando un Enum quali:implementazione Singleton con un Enum (in Java)

public enum MySingleton { 
    INSTANCE; 
} 

Ma, come fa il lavoro di cui sopra? Nello specifico, è necessario creare un'istanza di Object. Qui, come viene istanziato MySingleton? Chi sta facendo new MySingleton()?

+17

_Chi sta facendo nuova MySingleton() _ La JVM è. –

+24

'INSTANCE' è uguale a' public static final MySingleton INSTANCE = new MySingleton(); '. – Pshemo

+2

ENUM - Un singleton garantito. –

risposta

157

Questo,

public enum MySingleton { 
    INSTANCE; 
} 

ha un costruttore vuoto implicito. Cerchiamo di essere esplicito, invece,

public enum MySingleton { 
    INSTANCE; 
    private MySingleton() { 
     System.out.println("Here"); 
    } 
} 

Se poi aggiunto un'altra classe con un metodo main() come

public static void main(String[] args) { 
    System.out.println(MySingleton.INSTANCE); 
} 

vedreste

Here 
INSTANCE 

enum campi sono costanti di tempo di compilazione, ma sono istanze del loro tipo enum. E, sono costruiti quando il tipo enum è referenziato per la prima volta.

+6

È necessario aggiungere che per enumerazione predefinita è implicito un costruttore privato implicito e che l'aggiunta esplicita di un costruttore privato non è necessaria a meno che non si abbia effettivamente codice che è necessario eseguire in quel costruttore –

+0

ogni campo enum crea un'istanza solo una volta, quindi non è necessario creare costruttore privato. –

+1

public enum MySingleton {INSTANCE, INSTANCE1; } e quindi System.out.println (MySingleton.INSTANCE.hashCode()); System.out.println (MySingleton.INSTANCE1.hashCode()); stampa diversi hashcode. Significa che vengono creati due oggetti di MySingleton? –

3

Dal Singleton pattern è di avere un costruttore privato e chiamando un metodo per controllare le istanze (come alcuni getInstance), in enumerazioni abbiamo già un costruttore privato implicita.

io non so esattamente come il JVM o qualche contenitore controlla le istanze della nostra Enums, ma sembra che già utilizzano un implicito Singleton Pattern, la differenza è che non chiamiamo un getInstance, abbiamo appena chiama l'Enum.

8

Come tutte le istanze di enum, Java crea un'istanza di ogni oggetto quando la classe viene caricata, con la garanzia che viene istanziata esattamente una volta per JVM. Pensa alla dichiarazione INSTANCE come un campo finale statico pubblico: Java creerà un'istanza dell'oggetto per la prima volta in cui la classe viene indicata.

Le istanze vengono create durante l'inizializzazione statica, che è definita nello Java Language Specification, section 12.4.

Per quello che vale, Joshua Bloch descrive questo modello in dettaglio come articolo 3 di Effective Java Second Edition.

42

Un tipo enum è un tipo speciale di tipo class.

vostra dichiarazione enum realtà compila a qualcosa di simile

public final class MySingleton { 
    public final static MySingleton INSTANCE = new MySingleton(); 
} 

Quando il codice accede prima INSTANCE, la classe MySingleton verrà caricato e inizializzato dalla JVM. Questo processo inizializza il campo static sopra una volta (pigramente).

+0

Questa classe contiene anche costruttore privato()? Penso che sarebbe –

+1

@ yasir Sì, è corretto. –

+0

'public enum MySingleton { \t INSTANCE, INSTANCE1; } e quindi 'System.out.println (MySingleton.INSTANCE.hashCode()); \t System.out.println (MySingleton.INSTANCE1.hashCode()); 'stampa diversi hashcode. Significa che vengono creati due oggetti di MySingleton? –

51

In questo Java best practices book di Joshua Bloch, è possibile trovare il motivo per cui è necessario imporre la proprietà Singleton con un costruttore privato o un tipo Enum. Il capitolo è piuttosto lungo, quindi mantenendolo riassunto:

Fare una classe a Singleton può rendere difficile testare i suoi client, in quanto è impossibile sostituire un'implementazione di simulazione per un singleton a meno che non implementi un'interfaccia che funge da suo tipo . approccio positiva è attuare Singoletti semplicemente fare un tipo enum con un elemento:

// Enum singleton - the preferred approach 
public enum Elvis { 
INSTANCE; 
public void leaveTheBuilding() { ... } 
} 

Questo approccio è funzionalmente equivalente al metodo campo pubblico, tranne che è più conciso, fornisce il meccanismo di serializzazione libero, e fornisce una garanzia ironclad contro l'istanziazione multipla, anche a fronte di sofisticati attacchi di serializzazione o riflessione .

Mentre questo approccio deve ancora essere ampiamente adottato , un tipo enum singolo elemento è il modo migliore per attuare un singoletto.

0
enum Checks { 

    INSTANCE; 

    Checks() { 
     System.out.println("checks"); 
    } 

    public void dowork() { 
     System.out.println(" do work please "); 
    } 
} 

public class EnumSingelton { 

    public static void main(String[] args) { 
     Checks.INSTANCE.dowork(); 
    } 
}