2013-02-20 10 views
5

Se si esegue il codice riportato di seguito,unboxing di un oggetto boxed nulla getta NullPointerException inaspettato

public class Foo{ 
    public static void main(String[] args){ 
     int id = new Bar().getId(); // throws unexpected NullPointerException 
    } 

    private static class Bar{ 
     private final Integer id; 

     public Bar(){ 
      this(null); 
     } 

     public Bar(Integer id){ 
      this.id = id; 
     } 

     public Integer getId(){ 
      return id; 
     } 
    } 
} 

si otterrà la seguente stacktrace,

Exception in thread "main" java.lang.NullPointerException 
    at Foo.main(Foo.java:3) 

Come mai non c'è nessun avviso del compilatore o altro? IMHO è una sottigliezza piuttosto brutta con unboxing, o forse sono solo ingenuo.


Aggiungendo alla risposta fornita da @Javier, se si sta utilizzando Eclipse, è necessario eseguire le seguenti operazioni per attivare questa:

  1. Naviga a Finestra> Preferenze >Java>Compilatore>Errori/avvertenze
  2. Espandi problemi potenziali di programmazione
  3. Toggle Boxing e unboxing conversioni a uno "warning" o "Error"
  4. Toccare "OK"
+0

Non capisco. Stai chiedendo perché succede il NPE o questo è solo un rant? Quale sarebbe la specifica domanda rispondente? – madth3

risposta

5

non so che cosa IDE stai usando , ma Eclipse ha un'opzione per abilitare le avvertenze sulle conversioni di boxing e unboxing. Non è possibile rilevarlo come accesso a un puntatore nullo, poiché null non è immediatamente eliminato, ma tramite Bar.getId().

L'espressione di tipo intero è Unboxed in int linea
Foo.java 3

+0

Utilizzo Eclipse da ~ 3 anni e non lo sapevo! Dolce! – mre

+2

E 'fastidioso che Eclipse non possa attivare gli avvisi di casella vuota senza box! https://bugs.eclipse.org/bugs/show_bug.cgi?id=163065 – Kyle

3

Se si tenta di utilizzare qualsiasi metodo su un null o fare qualsiasi cosa che non ha senso con un null, getta un NullPointerException.

autounboxing è implementato con il metodo [Integer object].intValue() (o simili), in modo che getta un NullPointerException perché non si può avere null invocare un metodo.

Spero che questo aiuti!

+1

+1 per quel bit su 'intValue' dietro le quinte, grazie – mre

0

NullPointerException è un RuntimeException che IDE non è in grado di rilevare durante la compilazione del codice.

Invece, una buona pratica è il controllo null prima di unboxing.

int getId(){ 
    if(id!=null){ 
     return id; 
    } 
    // return other or throw a checked exception. 
} 
0

Sembra un'eccezione di tempo di esecuzione perfettamente ragionevole. Se il tuo codice principale era:

public static void main(String[] args){   
    Integer idObj = new Bar().getId(); 
    int id = idObj; // throws NullPointerException 
} 

Nessuno si stupirebbe dell'eccezione del puntatore nullo. La classe Bar restituisce un valore null e il puntatore di un oggetto nullo non può essere trasformato in un valore semplice. L'implementazione della classe Bar potrebbe essere modificata per inizializzare l'id su un valore non nullo.Questo blocco di codice può essere compilato indipendentemente dalla classe Bar, e quindi le ipotesi sul funzionamento dinamico della classe Bar non dovrebbero certamente essere codificate in questo blocco di codice.

Questo è probabilmente ovvio, ma la vera soluzione è utilizzare int per il membro id, anziché Integer. Questo, quindi, non ha alcun problema:

private static class Bar{ 
    private final int id; 

    public Bar(){ 
     this(0); 
    } 

    public Bar(int id){ 
     this.id = id; 
    } 

    public int getId(){ 
     return id; 
    } 
} 

(Ma immagino che già erano a conoscenza di questo :-))

+0

non ho detto che l'eccezione era irragionevole, ho detto che era inaspettato, soprattutto dal momento che il mio IDE ha scelto di ignorarlo per impostazione predefinita. – mre

+0

OK, stavo cercando di aggirare ciò che è "previsto" e "inaspettato". È un'eccezione run-time, non qualcosa che può essere necessariamente determinato dall'analisi statica. Come ti aspetteresti che l'IDE si comporti in questa situazione? – AgilePro

+0

Mi aspettavo che l'IDE mi avvisasse almeno per impostazione predefinita. Come ho detto, penso che sia un'eccezione di runtime piuttosto sottile. – mre

4

sembra che questo comportamento è documentato nella JDK™ 5.0 Documentation,

..si può ignorare in gran parte la distinzione tra int e Integer, con alcuni avvertimenti. Un'espressione Integer può avere un valore nullo. Se il tuo programma tenta di autounbox null, genererà uno NullPointerException.

0

Boxe non è altro che lo zucchero sintattico per la fusione di un oggetto come Integer al nativo equivalente 'int'. I nativi non possono essere nulli ma gli oggetti possono. Il meccanismo di boxe non impedirà NullPointerExceptions in questi casi.

Problemi correlati