La prima cosa da tenere a mente è che gli operatori ternari Java hanno un "tipo" e che questo è ciò che il compilatore determinerà e considererà indipendentemente dai tipi reali / reali del secondo o terzo parametro. A seconda di diversi fattori, il tipo di operatore ternario viene determinato in diversi modi, come illustrato nella specifica del linguaggio Java 15.26
Nella domanda sopra dovremmo considerare l'ultimo caso:
Altrimenti, il secondo e il terzo operando sono rispettivamente di tipo S1 e S2 . Sia T1 il tipo risultante dall'applicazione della conversione del pugilato a S1 e T2 sia il tipo risultante dall'applicazione della conversione del pugilato a S2 . Il tipo dell'espressione condizionale è il risultato dell'applicazione della conversione della cattura (§5.1.10) in lub (T1, T2) (§15.12.2.7).
Questo è di gran lunga il caso più complesso dopo aver dato un'occhiata all'applicazione della conversione di cattura (§5.1.10) e soprattutto a lub (T1, T2) .
In parole povere e dopo un'estrema semplificazione possiamo descrivere il processo come il calcolo della "Minima Superclasse Comune" (sì, pensa alla LCM) del secondo e terzo parametro. Questo ci darà l'operatore "tipo" ternario. Ancora una volta, ciò che ho appena detto è un'estrema semplificazione (considera le classi che implementano più interfacce comuni).
Ad esempio, se provi quanto segue:
long millis = System.currentTimeMillis();
return(true ? new java.sql.Timestamp(millis) : new java.sql.Time(millis));
Noterai che il tipo risultante dell'espressione condizionale è java.util.Date
dato che è la "Superclass meno comune" per Timestamp
/Time
coppia .
Poiché null
può essere autoboxato su qualsiasi cosa, la "Superclass comune minima" è la Integer
classe e questo sarà il tipo restituito dell'espressione condizionale (operatore ternario) sopra. Il valore restituito sarà quindi un puntatore null di tipoInteger
e questo è ciò che verrà restituito dall'operatore ternario.
In fase di esecuzione, quando la Java Virtual Machine unboxes l' Integer
una NullPointerException
è gettato. Ciò accade perché JVM tenta di richiamare la funzione null.intValue()
, dove null
è il risultato del box automatico.
Secondo me (e poiché la mia opinione non è nella specifica del linguaggio Java, molte persone lo troveranno comunque sbagliato) il compilatore fa un pessimo lavoro nel valutare l'espressione nella tua domanda. Dato che hai scritto true ? param1 : param2
il compilatore dovrebbe determinare immediatamente che il primo parametro - null
- verrà restituito e dovrebbe generare un errore del compilatore. Questo è in qualche modo simile a quando scrivi while(true){} etc...
e il compilatore si lamenta del codice sotto il ciclo e lo contrassegna Unreachable Statements
.
Il tuo secondo caso è piuttosto semplice e questa risposta è già troppo lunga ...;)
CORREZIONE:
Dopo un'altra analisi, credo di aver sbagliato a dire che un null
valore può essere inscatolato / autoboxato su qualsiasi cosa. Parlando della classe Integer, il boxing esplicito consiste nell'invocare il new Integer(...)
costruttore o forse il Integer.valueOf(int i);
(ho trovato questa versione da qualche parte). Il primo lancerebbe un NumberFormatException
(e questo non accade) mentre il secondo non avrebbe senso dal momento che un int
non può essere null
...
int foo = (true ? null : 0)
ednew Integer(null)
entrambi compilano bene, il secondo è la forma esplicita di autoboxing.