Авто-распаковка нужна троичного if-else - PullRequest
23 голосов
/ 04 марта 2020

Этот фрагмент кода работает нормально: -

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

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

Ответы [ 4 ]

22 голосов
/ 04 марта 2020

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

1 <= 3 ? nullInt : -1

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

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

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

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

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

3 голосов
/ 04 марта 2020

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

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

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

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

3 голосов
/ 04 марта 2020

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

2 голосов
/ 19 марта 2020

Этот работал (в Java 1,8):

Integer secondNull = 1 <= 3 ? null : -1;
...