Перше, що слід пам’ятати, це те, що потрійні оператори 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 розблоковує , викидається Integera 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)обидва складають штрафи, друга є явною формою автобоксингу.