Разница заключается в статической типизации выражений во время компиляции:
Краткое описание
E1: `(false ? 1.0f : null)`
- arg 2 '1.0f' : type float,
- arg 3 'null' : type null
- therefore operator ?: : type Float (see explanation below)
- therefore autobox arg2
- therefore autobox arg3
E2: `(false ? 1.0f : (false ? 1.0f : null))`
- arg 2 '1.0f' : type float
- arg 3 '(false ? 1.0f : null)' : type Float (this expr is same as E1)
- therefore, outer operator ?: : type float (see explanation below)
- therefore un-autobox arg3
Подробное объяснение:
Вот мое понимание чтения спецификации и работы в обратном направлении от полученного результата. Это сводится к типу третьего операнда условного выражения f2 inner нулевого типа, в то время как тип третьего операнда условного выражения f2 external считается Float.
Примечание: Важно помнить, что определение типа и вставка кода блокировки / распаковки выполняется во время компиляции. Фактическое выполнение кода упаковки / распаковки выполняется во время выполнения.
Float f1 = (false ? 1.0f : null);
Float f2 = (false ? 1.0f : (false ? 1.0f : null));
Условное f1 и внутреннее условное f2: (false? 1.0f: null)
Условные выражения f1 и внутренние условные выражения f2 идентичны: (false? 1.0f: null) . Типы операндов в условном f1 и внутреннем условном f2:
type of second operand = float
type of third operand = null type (§4.1)
Большинство правил в §15.25 пропущены, и эта окончательная оценка действительно применяется:
В противном случае второй и третий операнды имеют типы S1 и S2 соответственно. Пусть T1 будет типом, который получается в результате применения преобразования в бокс для S1, и пусть T2 будет типом, который получается в результате применения преобразования в бокс в S2. Тип условного выражения является результатом применения преобразования захвата ( §5.1.10 ) к lub (T1, T2) ( §15.12.2.7 ).
S1 = float
S2 = null type
T1 = Float
T2 = null type
type of the f1 and f2 inner conditional expressions = Float
Поскольку для f1 присваивание является ссылочной переменной Float, результат выражения (null) успешно назначен.
Для внешнего условия f2: (false? 1.0f: [внутреннее условие f2])
Для внешнего условного выражения f2 возможны следующие типы:
type of second operand = float
type of third operand = Float
Обратите внимание на разницу в типах операндов по сравнению с внутренними условными выражениями f1 / f2, которые напрямую ссылаются на литерал null ( §4.1 ). Из-за этого различия в наличии двух числово-конвертируемых типов применяется правило из §15.12.2.7 :
В противном случае, если второй и третий операнды имеют типы, которые могут быть преобразованы ( §5.1.8 ) в числовые типы, то существует несколько случаев: ...
- В противном случае двоичное числовое продвижение ( §5.6.2 ) применяется к типам операндов, а тип условного выражения является продвинутым типом второго и третьего операндов. Обратите внимание, что двоичное числовое продвижение выполняет преобразование без ящика ( §5.1.8 ) и преобразование набора значений ( §5.1.13 ).
Из-за преобразования распаковки, выполненного в результате внутреннего условного выражения f2 (null), возникает исключение NullPointerException.