Получение нежелательного NullPointerException в тройном операторе - Почему?

Выполняя следующий код, я получаю NullPointerException:

value = condition ? getDouble() : 1.0;

В более ранних строках, когда я использую null вместо getDouble() все работает, и это странно.

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);
    }
}

Может ли кто-нибудь помочь мне понять это поведение?

Ответ 1

Когда вы пишете

value = condition ? null : 1.0;

тип condition? null: 1.0 condition? null: 1.0 должен быть ссылочным типом, поэтому тип Double, который может содержать значение null.

Когда вы пишете

value = condition ? getDouble() : 1.0;

и getDouble() возвращает null, что эквивалентно записи:

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

В этом случае компилятор видит Double и double как 2-й и 3-й аргументы тернарного условного оператора и решает, что тип выражения должен быть double. Поэтому он освобождает значение null до double, получая NullPointerException.

Тип условного тернарного оператора определяется некоторыми таблицами в JLS 15.25.

Если 2-й и 3-й операнды равны null и double, тип условного выражения является наименьшей верхней границей Double и null, которая является Double.

Если 2-й и 3-й операнды Double и double, тип условного выражения double.

Ответ 2

См. # Jls-15.25:

enter image description here

Если второй операнд Double, в то время как третий операнд double, результат:

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

будет double.

И когда вы попытаетесь преобразовать Double null (возвращенный getDouble()), чтобы double, NPE будет выброшен.