Первое, что нужно иметь в виду, это то, что троичные операторы 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
...