2013-03-26 5 views
6

Ho questo Singleton Sto cercando di usare, ma a quanto pare getInstance può restituire null:Java Singleton.getInstance() restituisce null?

class Singleton { 
    public static final String K_LEVEL = "level"; 
    static Singleton instance = new Singleton(); 
    private int level; 

    static Singleton getInstance() { 
     return instance; 
    } 

    int getLevel() { 
     return level; 
    } 

    void incrementLevel() { 
     System.out.println("LEVEL INCREASED TO " + ++level); 
    } 

    void addToLevel(int x) { 
     for(int i=0;i<x;i++) 
      incrementLevel(); 
    } 

} 

class A { 
    public static void main(String[] args) { 
     Singleton s = Singleton.getInstance(); 
     Integer i = Integer.getInteger(Singleton.K_LEVEL); 
     s.addToLevel(i); 
    } 
} 

Ho sentito singletons implementazione in Java è molto difficile e soggetta a condizioni di gara. Il mio schema singleton è stato implementato in modo errato? Recentemente ho cambiato il mio codice per assomigliare a questo, e ora getInstance restituisce null a volte. Perché?

$ java A -Dlevel=1 
Exception in thread "main" java.lang.NullPointerException 
    at A.main(A.java:29) 
+1

Cosa significa 'System.out.println (i);' prima di 's.addToLevel (i);' stampa? – jlordo

risposta

2

Non c'è niente di sbagliato in Singleton. Non ci sono problemi di concorrenza perché questo non è un codice multithread.

Stavi pensando che s era nullo, ma è davvero i che era nullo.

Dal addToLevel prende un int come parametro, il Integer i stato autounboxed (implicitamente convertito da Integer a int), ma dal momento che era inull, NullPointerException fu gettato. Autounboxing genera NullPointerException quando il valore da coprire è null.

Il motivo Integer.getInteger(Singleton.K_LEVEL) restituito null è perché è stato effettuato java A -Dlevel=1 anziché java -Dlevel=1 A. Quest'ultima è la sintassi corretta.

2

Questo non riguarda il tuo modello di singleton che mi sta bene. È il metodo Integer.getInteger(Singleton.K_LEVEL); che restituisce null. Scommetto che la proprietà di sistema "level" non è stata impostata ed è null.

Dai miei commenti, è necessario inserire -Dlevel=1prima della classe nella riga A sulla riga di comando. Se esegui il debug del tuo codice o stampi la proprietà di sistema, vedrai che è nullo.

si ottiene un NPE quando si tenta di passare il null in addToLevel(int x) e cerca di auto-Unbox il null essere int x.

Per inciso, se questa classe viene utilizzata da più thread, è consigliabile prendere in considerazione l'utilizzo di AtomicInteger all'interno della classe Singleton che è rientrante.

+0

No, l'ho impostato in questo modo: 'java A -Dlevel = 1' – Dog

+1

Il' -D' deve essere _before_ la classe 'A' @Dog. Eseguire il debug del codice o stampare la proprietà di sistema per verificarlo. – Gray

+1

Sono d'accordo. @ Dog perché non si stampa prima di chiamare addToLevel per verificare. –

1

java -Dlevel=1 A dovrebbe soddisfare le vostre esigenze.

Dal doc, la sintassi è java [ options ] class [ argument ... ] e -Dlevel=1 è considerato come opzione (vedere la sezione options).

0

static Singleton instance = new Singleton(); dovrebbe essere definitivo per evitare condizioni di gara.