Перше, що слід пам’ятати, це те, що потрійні оператори Java мають «тип», і що саме це визначатиме компілятор і враховує, незалежно від того, які фактичні / реальні типи другого або третього параметра. Залежно від декількох факторів тип потрійного оператора визначається різними способами, як показано в специфікації мови Java 15.26
У вищезазначеному питанні ми повинні розглянути останній випадок:
В іншому випадку другий і третій операнди мають типи S1 і S2 відповідно. Нехай T1 - тип, який є результатом застосування перетворення боксу до S1 , а T2 - тип, який є результатом застосування перетворення боксу до S2 . Тип умовного виразу є результатом застосування перетворення захоплення (§5.1.10) до лубу (T1, T2) (§15.12.2.7).
Це, безумовно, найскладніший випадок, коли ви подивитесь на застосування конверсії захоплення (§5.1.10), а найбільше - на луб (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)
обидва складають штрафи, друга є явною формою автобоксингу.