web-dev-qa-db-fra.com

Obtenir une exception NullPointerException indésirable dans un opérateur ternaire - Pourquoi?

En exécutant le code suivant, je reçois un NullPointerException à la ligne:

value = condition ? getDouble() : 1.0;

Dans les lignes précédentes, lorsque j'utilise null au lieu de getDouble(), tout fonctionne et c'est étrange.

public class Test {
    static Double getDouble() {
        return null;
    }

    public static void main(String[] args) {
        boolean condition = true;
        Double value;

        value = condition ? null : 1.0;         //works fine
        System.out.println(value);              //prints null

        value = condition ? getDouble() : 1.0;  //throws NPE
        System.out.println(value);
    }
}

Est-ce que quelqu'un peut m'aider à comprendre ce comportement?

48
Joker

Quand tu écris

value = condition ? null : 1.0;

le type de condition ? null : 1.0 doit être un type de référence; le type est donc Double, qui peut contenir la valeur null.

Quand tu écris

value = condition ? getDouble() : 1.0;

et getDouble() renvoie null, cela équivaut à écrire:

value = condition ? ((Double) null) : 1.0;

Dans ce cas, le compilateur considère que Double et double sont les deuxième et troisième arguments de l'opérateur conditionnel ternaire et décide que le type de l'expression doit être double. Par conséquent, il décompresse le null en double, obtenant ainsi NullPointerException.

Le type de l'opérateur ternaire conditionnel est déterminé par certaines tables de JLS 15.25 .

Si les deuxième et troisième opérandes sont null et double, le type d'expression conditionnelle est la limite supérieure inférieure de Double et null, qui est Double.

Si les deuxième et troisième opérandes sont Double et double, le type d'expression conditionnelle est double.

77
Eran

Voir # jls-15.25 :

enter image description here

Si le deuxième opérande est Double alors que le troisième opérande est double, le résultat:

getCount() == 1 ? getDouble() : 1.0

sera un double.

Et lorsque vous essayez de convertir un Double null (Renvoyé par getDouble()) en double, NPE sera levé.

23
xingbin