Авто-распаковка нужна троичного if-else

23

Этот кусок кода работает нормально: -

    Integer nullInt = null;
    if (1 <= 3) {
        Integer secondNull = nullInt;
    } else {
        Integer secondNull = -1;
    }
    System.out.println("done");

Но это вызывает исключение нулевого указателя, а Eclipse предупреждает о необходимости автоматической распаковки: -

    Integer nullInt = null;
    Integer secondNull = 1 <= 3 ? nullInt : -1;
    System.out.println("done");

Почему это так, кто-нибудь может помочь, пожалуйста?

91StarSky
источник

Ответы:

22

Тип троичного условного выражения

1 <= 3 ? nullInt : -1

is int(JLS содержит несколько таблиц, которые описывают тип троичного условного оператора в зависимости от типов 2-го и 3-го операндов).

Поэтому, когда он пытается распаковать nullIntв inta NullPointerException, выбрасывается.

Чтобы узнать поведение вашего фрагмента if-else, вам нужно написать:

1 <= 3 ? nullInt : Integer.valueOf(-1)

Теперь тип выражения будет таким Integer, чтобы не было распаковки.

Эран
источник
4
Просто чтобы добавить в свой ответ, вот упомянутые таблицы: docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25
Amongalen
3

Я почти уверен, что аргументы троичного оператора должны быть такого же типа. Так как вы используете -1 и некоторый константный nullintкомпилятор пытается распаковать, nullintчтобы получить значение. А затем автобокс его хранить в secondNullпеременной.

Тостеры
источник
3

Это происходит потому, что, когда два операнда для условного оператора ? :являются примитивным типом и его ссылочным типом в штучной упаковке, выполняется преобразование без распаковки ( JLS §15.25.2 ):

Тип числового условного выражения определяется следующим образом:

  • ...
  • Если один из второго и третьего операндов имеет примитивный тип T, а тип другого является результатом применения преобразования в бокс (§5.1.7) к T, то тип условного выражения - T.

В общем случае замена ifоператора ? :выражением не всегда сохраняет смысл кода, поскольку само ? :выражение должно иметь тип времени компиляции. Это означает, что когда типы двух операндов различны, необходимо выполнить преобразование в один или оба, чтобы у результата был согласованный тип времени компиляции.

kaya3
источник
2

Этот работал (в Java 1.8):

Integer secondNull = 1 <= 3 ? null : -1;
Каталина Чирку
источник