NullPointerException в троичном выражении с нулем Long

Почему следующая строка кода создает NullPointerException?

Long v = 1 == 2 ? Long.MAX_VALUE : (Long) null;

Я понимаю, что распаковка производится на null, но почему?

Обратите внимание, что

Long v = (Long) null;

Не создает исключение.


person jonderry    schedule 15.12.2011    source источник
comment
Вы делаете v=((1==2)?Long.MAX_VALUE : (Long) null); это всегда ложно, поэтому вы всегда пытаетесь преобразовать значение null в значение Long. Это кажется недопустимым и выдает ваше исключение.   -  person evildead    schedule 15.12.2011
comment
Зачем тебе такая строчка кода? Интеллектуальное любопытство или это фрагмент реального производственного кода?   -  person Paul    schedule 15.12.2011
comment
@Paul и evildead выглядит как пример кода, демонстрирующий порядок распаковки.   -  person Steven    schedule 15.12.2011
comment
Это связано с java.sun.com/ документы/книги/jls/третье_издание/html/   -  person Steven    schedule 15.12.2011
comment
@Paul, это из производства, но упрощено для создания исключения в простом коде.   -  person jonderry    schedule 15.12.2011
comment
Почему бы вам не разбить тернарный оператор на if/then/else? Это может помочь вам разобраться в этом.   -  person Paul    schedule 15.12.2011
comment
Это с производства? Еще раз, читабельность побеждает ум...   -  person Paul    schedule 15.12.2011
comment
@Paul Если вы расскажете об этом, если / то / иначе проблема исчезнет.   -  person Tom Hawtin - tackline    schedule 15.12.2011
comment
Прерывание его на if then else приводит к исчезновению исключения. Мне просто интересно, почему троичный синтаксис вызывает это исключение.   -  person jonderry    schedule 15.12.2011
comment
Связано: stackoverflow.com/questions/3882095/ Кстати, решение состоит в том, чтобы переместить это приведение в ваш Long.MAX_VALUE, поскольку оно возвращает long.   -  person BalusC    schedule 15.12.2011
comment
@ Том, тогда они должны удалить все такие экземпляры из кода, заставить парня, который их написал, купить пончики для команды, а затем прочитать в порядке приоритета.   -  person Paul    schedule 15.12.2011


Ответы (2)


Таким образом, кажется очевидным, что вам нужно боксировать только в том случае, если условие истинно, и не должно быть бокса, если условие ложно. Однако выражение тернарного оператора должно иметь определенный тип static. Итак, у нас есть Long и long. JLS утверждает, что результатом будет примитив (точно так же — представьте, если бы оператор был, скажем, + или даже ==). Таким образом, тернарный оператор принудительно распаковывает, и только тогда присваивание вызывает упаковку.

Если бы вы заменили код на эквивалентный if-else, то у вас было бы просто назначение от long до Long и от Long до Long, которое не распаковывалось и поэтому работало нормально.

IIRC, это покрыто Java Puzzlers от Bloch & Gafter.

person Tom Hawtin - tackline    schedule 15.12.2011

Из JSL

  1. Если второй и третий операнды имеют одинаковый тип (который может быть нулевым типом), то это тип условного выражения.
  2. Если один из второго и третьего операндов имеет тип boolean, а тип другого — тип Boolean, то тип условного выражения — boolean.

В следующем операторе тип второго операнда — long, а третьего — Long.

Long v = 1 == 2 ? Long.MAX_VALUE :  (Long) null;

Это будет работать, если выражение истинно.

Long v= 1 == 1 ?  Long.MAX_VALUE : (Long) null;

Или вы можете бросить его.

Long v= 1 == 2 ?  Long.valueOf(Long.MAX_VALUE) : (Long) null;
person kv-prajapati    schedule 15.12.2011
comment
Да, я знаю, что он выполняет распаковку, и что вы не можете распаковать null. Я спрашивал, почему он пытается выполнить распаковку в этом случае. - person jonderry; 15.12.2011
comment
Это не совсем правильно. Он пытается распаковать нулевой объект Long; актерский состав не проблема. Вы можете привести null к любому типу объекта, см. спецификацию языка Java раздел 5.5 в разделе Если приведение к ссылочному типу не является ошибкой времени компиляции, существует несколько случаев: - person Paul; 15.12.2011