2014-10-18 10 views
10

Ho un parte di codice come questo:Perché l'assegnazione di un valore nullo da un'istruzione ternaria a una variabile booleana genera un valore NPE?

public static void main(String[] args) throws Exception { 
    String trueValue = Boolean.TRUE.toString(); 
    String fieldValue = null; 
    Boolean defaultValue = null; 

    Boolean value = (fieldValue != null ? trueValue.equalsIgnoreCase(fieldValue) : defaultValue); 

    System.out.println(value); 
} 

Quando defaultValue non è uguale a null il codice funziona bene, ma quando è defaultValuenull JVM tiri un NullPointerException. Questo codice è stato compilato usando jdk 1.6.45.

Perché ho ricevuto questa eccezione?

+0

Perché in Java un valore booleano non può essere null. – Titus

+3

@Titus ma Boolean può booleano non può –

+0

cosa stai cercando di fare nell'operatore ternario ?? –

risposta

9

È l'operatore ternario. Poiché la prima opzione trueValue.equalsIgnoreCase(fieldValue) è un valore booleano, sembra presupporre che la seconda opzione defaultValue sia un valore booleano anziché un valore nullo Boolean. È strano, ma sembra che stia succedendo. Se lanci la prima opzione per Boolean, l'errore va via:

Boolean value = (fieldValue != null ? (Boolean) trueValue.equalsIgnoreCase(fieldValue) : defaultValue); 
12

Java language specification dice:

Se una delle seconde e terze operandi è di tipo primitivo T, e il tipo degli altri è il risultato dell'applicazione della conversione di boxe (§5.1.7) a T, quindi il tipo di espressione condizionale è T.

8

Dal JLS: 15.25. Conditional Operator ? :

Se una delle seconde e terze operandi è di tipo primitivo T, e il tipo di l'altro è il risultato dell'applicazione di conversione boxe (§5.1.7) per T , quindi il tipo di espressione condizionale è T.

Aka: quando il 2 ° e il 3 ° operando sono di tipo primitivo e in scatola, il risultato è considerato il tipo primitivo. Alla fine della tua operazione lo stai rileggendo di nuovo, ma a quel punto hai già provato a assegnare null a un tipo primitivo, cosa che non è possibile.

La firma di String#equalsIgnoreCase è ...

public boolean equalsIgnoreCase 
+2

+1, anche se "già provato ad assegnare' null' a un tipo primitivo "sarebbe meglio scrivere come" già provato a ** unbox ** 'null' a un tipo primitivo", o forse come "già implicitamente chiamato' valore booleano() 'su un riferimento' null'. – ruakh

Problemi correlati