Тройные условия Java, странное исключение нулевого указателя

Может кто-нибудь объяснить мне, почему в первом случае был обнаружен нулевой указатель, а в другом нет?

Может он всегда смотрит на первый тип, но почему он так делает только если условие ложно..

@Test
public void test1() {
    final Integer a = null;

    final Integer b = false ? 0 : a;

    //===> NULL POINTER EXCEPTION
}

@Test
public void test2() {
    final Integer b = false ? 0 : null;

    //===>NOT NULL POINTER EXCEPTION
}

@Test
public void test3() {
    final Integer a = null;

    final Integer b = true ? 0 : a;

    //===>NOT NULL POINTER EXCEPTION
}

@Test
public void test4() {
    final Integer a = null;

    final Integer b = false ? new Integer(0) : a;

    //===> NOT NULL POINTER EXCEPTION
}

@Test
public void test5() {
    final Integer a = null;

    final Integer b = false ? a : 0;

    //===>NOT NULL POINTER EXCEPTION
}

person Kimo_do    schedule 29.06.2016    source источник
comment
Возможный обман: stackoverflow.com/questions/12763983/ (я не голосую за то, чтобы не закрывать вопрос)   -  person    schedule 29.06.2016
comment
Если один из второго и третьего операндов имеет примитивный тип T, а тип другого — результат применения преобразования упаковки (§5.1.7) к T, то тип условного выражения — T. Так почему test3 и test5 не бросил NPE? извините, я не понял   -  person Kimo_do    schedule 29.06.2016


Ответы (2)


Когда вы используете тернарный оператор,

 flag  ? type1 : type2

Type1 и type2 должны быть одного типа при преобразовании. Сначала он реализует type1, а затем type2.

Теперь посмотрите на свои дела

 final Integer b = false ? 0 : a;

Так как type1 это 0 и принимает за примитив, а так как a пытается преобразовать его в primitive. Отсюда и нулевой указатель.

где такой же хитрый тест5

 final Integer b = false ? a : 0;

Поскольку a имеет тип Integer 0, упакованный в целое число-оболочку и назначенный LHS.

person Suresh Atta    schedule 29.06.2016
comment
Этот ответ объясняет на другом уровне, что говорит предыдущий ответ. (причина вызова null.intValue(). Хороший ответ ;-) - person Dylan Meeus; 29.06.2016
comment
Спасибо за ваш ответ, можете ли вы объяснить, почему test3 не выдал NPE? почему преобразование не было применено к «типу 1», поэтому преобразование в примитив? - person Kimo_do; 29.06.2016
comment
final Integer b = true ? 0 : a; Поскольку флаг истинен, он выбрал 0. и бокс происходит с новым целым числом (0). Ноль - действительное целое число, верно? - person Suresh Atta; 29.06.2016
comment
преобразование происходит с истинным элементом, а не с первым. Я понимаю ! Спасибо - person Kimo_do; 29.06.2016

Я думаю, что в этом случае a будет распакован в int, потому что 0 — это int. Это означает, что null.intValue() вызывается и получает NPE

@Test
public void test1() {
    final Integer a = null;

    final Integer b = false ? 0 : a;
person Jens    schedule 29.06.2016
comment
ну я не уверен, что это причина. Почему тогда test4 не выдает NPE? - person Dylan Meeus; 29.06.2016
comment
Проблема в том, что java интерпретирует a как int из-за? - person ; 29.06.2016
comment
На самом деле он будет не упакован в int. Но мне интересно, почему test2, кажется, упаковывает его, а test1, кажется, распаковывает его ... но @DylanMeeus, это потому, что ничего не вызывается для null в тесте 4, поскольку там не выполняется (un) упаковка. - person Siguza; 29.06.2016
comment
В test4 a в целом, поэтому b также будет интерпретироваться как целое число. - person Jens; 29.06.2016
comment
@ Дженс, ты прав. Выполнение javap -c в коде показывает, что вызываются как intValue(), так и valueOf() ;-) Что не относится к test 4. (Что касается ответа на мой собственный вопрос в комментариях: P - person Dylan Meeus; 29.06.2016
comment
If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T. - вот почему тест 2 работает, а тест 1 не работает. null в тесте 2 не распаковывается, так как не соответствует указанным критериям (взято из JLS). - person Eran; 29.06.2016