Первое, что нужно иметь в виду, это то, что троичные операторы Java имеют «тип», и именно это компилятор будет определять и учитывать независимо от того, что является действительным / реальным типом второго или третьего параметра. В зависимости от нескольких факторов тип троичного оператора определяется по-разному, как показано в спецификации языка Java 15.26.
В приведенном выше вопросе мы должны рассмотреть последний случай:
В противном случае второй и третий операнды имеют типы S1 и S2 соответственно. Пусть T1 будет типом, который получается в результате применения преобразования в бокс для S1 , и пусть T2 будет типом, который получается в результате применения преобразования в бокс в S2 . Тип условного выражения является результатом применения преобразования захвата (§5.1.10) к lub (T1, T2) (§15.12.2.7).
Это, безусловно, самый сложный случай, когда вы смотрите на применение преобразования захвата (§5.1.10) и больше всего на lub (T1, T2) .
Простым английским языком и после крайнего упрощения мы можем описать процесс как вычисление «Наименьшего общего суперкласса» (да, подумайте о LCM) второго и третьего параметров. Это даст нам троичный оператор «тип». Опять же, то, что я только что сказал, является крайним упрощением (рассмотрим классы, которые реализуют несколько общих интерфейсов).
Например, если вы попробуете следующее:
long millis = System.currentTimeMillis();
return(true ? new java.sql.Timestamp(millis) : new java.sql.Time(millis));
Вы заметите, что результирующий тип условного выражения - java.util.Date
это «Наименьший общий суперкласс» для пары Timestamp
/ Time
.
Так как null
может быть автоматически помещен во что угодно, «Наименьший общий суперкласс» является Integer
классом, и это будет тип возврата условного выражения (тернарный оператор) выше. Тогда возвращаемое значение будет нулевым указателем типаInteger
и именно это будет возвращено троичным оператором.
Во время выполнения, когда виртуальная машина Java распаковывает , выбрасывается Integer
a NullPointerException
. Это происходит потому, что JVM пытается вызвать функцию null.intValue()
, где null
есть результат автобоксирования.
По моему мнению (и поскольку мое мнение не в спецификации языка Java, многие люди все равно сочтут его неправильным), компилятор плохо справляется с оценкой выражения в вашем вопросе. Учитывая, что вы написали, true ? param1 : param2
компилятор должен сразу определить, что null
будет возвращен первый параметр -, и это должно вызвать ошибку компилятора. Это похоже на то, когда вы пишете, while(true){} etc...
и компилятор жалуется на код под циклом и помечает его как Unreachable Statements
.
Ваш второй случай довольно прост, и этот ответ уже слишком длинный ...;)
ИСПРАВЛЕНИЕ:
После другого анализа я считаю, что я был неправ, говоря, что null
значение может быть упаковано / автоматически упаковано для чего угодно. Говоря о классе Integer, явный бокс состоит в вызове new Integer(...)
конструктора или, возможно, Integer.valueOf(int i);
(я где-то нашел эту версию). Первый бросил бы NumberFormatException
(а этого не происходит), а второй просто не имел бы смысла, поскольку не int
может быть null
...
int foo = (true ? null : 0)
иnew Integer(null)
как скомпилироваться, второе явный вид Autoboxing.