2012-08-10 20 views
16

Per esempio:Perché il compilatore Java a volte consente l'annullamento del blocco di null?

int anInt = null; 

fallisce al momento della compilazione, ma

public static void main(String[] args) { 
    for (int i = 0; i < 10; i++) { 
    System.out.println("" + getSomeVal()); 
    } 
} 
public static int getSomeVal() { 
    return new Random().nextBoolean() ? 1 : null; 
} 

fallisce (di solito) in fase di esecuzione. Provare a restituire solo null comporterà anche un errore di compilazione, quindi presumo ci sia qualcosa sull'avere più percorsi che induca il compilatore a dedurre che null è potenzialmente un autoboxed int? Perché javac non riesce a compilare entrambi i casi con lo stesso errore?

risposta

20

Nel primo caso, il compilatore sa che si sta tentando di annullare la chiusura di una costante in fase di compilazione di null.

Nel secondo caso, il tipo dell'espressione condizionale è Integer, così si sta effettivamente scrivendo:

Integer tmp = new Random().nextBoolean() ? 1 : null; 
return (int) tmp; 

... quindi l'unboxing non sta accadendo su un'espressione costante, e il compilatore lo permetterà.

Se è stata modificata per forzare l'espressione condizionale essere di tipo int da spacchettamento , fallirebbe:

// Compile-time failure 
return new Random().nextBoolean() ? 1 : (int) null; 
+0

Il primo caso implica un "tipo" nullo che viene inoltrato implicitamente a un tipo int, r esultando in un errore del compilatore.Il secondo caso converte implicitamente null nel tipo di variabile di sinistra, che è il tipo di espressione piuttosto che il valore di ritorno. Immagino una lettura attenta di JLS 15.25 "Se il secondo e il terzo operando hanno lo stesso tipo (che può essere il tipo nullo), allora questo è il tipo di espressione condizionale." questo ti dà, dato che il compilatore java non può dare a null un tipo di int e quindi è costretto a usare Integer per entrambi unboxing del 1. Risposta molto chiara, grazie. – MilesHampson

2

inscatolamento nasconde parzialmente la distinzione tra primitive e corrispondenti oggetti wrapper, ma doesn rimuovilo.

Ci sono due distinzioni che non vengono modificate da boxe:

  • oggetti può essere nullo, mentre primitive non possono
  • oggetti avere sia stato e identità, mentre primitive hanno solo stato (il valore)

Occasionalmente, queste differenze possono causare problemi durante l'utilizzo della boxe.

Alcuni punti da ricordare:

  • stare attenti con i null. L'eliminazione automatica di un oggetto nullo causerà uno NullPointerException.
  • confrontare articoli con == e equals deve essere eseguito con attenzione.
1

Non è possibile assegnare null per un int

int anInt = null; 

Java consente questo dal momento che non si assegna null per un int

System.out.println("" + getSomeVal()); //null was just converted to a srting and was printed 

Se si esegue questa operazione, è possibile ottenere il errore

int anInt = getSomeVal(); 
Problemi correlati