Das erste, was zu beachten ist, ist, dass ternäre Java-Operatoren einen "Typ" haben und dass dies vom Compiler bestimmt und berücksichtigt wird, unabhängig davon, welche tatsächlichen / realen Typen der zweite oder dritte Parameter sind. Abhängig von mehreren Faktoren wird der ternäre Operatortyp auf unterschiedliche Weise bestimmt, wie in der Java-Sprachspezifikation 15.26 dargestellt
In der obigen Frage sollten wir den letzten Fall betrachten:
Ansonsten sind der zweite und der dritte Operand vom Typ S1 bzw. S2 . Sei T1 der Typ, der sich aus der Anwendung der Boxkonvertierung auf S1 ergibt , und sei T2 der Typ, der sich aus der Anwendung der Boxkonvertierung auf S2 ergibt . Der Typ des bedingten Ausdrucks ergibt sich aus der Anwendung der Capture-Konvertierung (§5.1.10) auf lub (T1, T2) (§15.12.2.7).
Dies ist bei weitem der komplexeste Fall, wenn Sie sich die Anwendung der Capture-Konvertierung (§5.1.10) und vor allem lub (T1, T2) ansehen .
Im Klartext und nach einer extremen Vereinfachung können wir den Prozess als Berechnung der "Least Common Superclass" (ja, denken Sie an das LCM) des zweiten und dritten Parameters beschreiben. Dies gibt uns den ternären Operator "Typ". Was ich gerade gesagt habe, ist eine extreme Vereinfachung (betrachten Sie Klassen, die mehrere gemeinsame Schnittstellen implementieren).
Wenn Sie beispielsweise Folgendes versuchen:
long millis = System.currentTimeMillis();
return(true ? new java.sql.Timestamp(millis) : new java.sql.Time(millis));
Sie werden feststellen, dass der resultierende Typ des bedingten Ausdrucks java.util.Date
die "Least Common Superclass" für das Timestamp
/ Time
pair ist.
Da null
für alles eine Autobox erstellt werden kann, ist die "Least Common Superclass" die Integer
Klasse und dies ist der Rückgabetyp des obigen bedingten Ausdrucks (ternärer Operator). Der Rückgabewert ist dann ein Nullzeiger vom Typ, Integer
und dieser wird vom ternären Operator zurückgegeben.
Zur Laufzeit, wenn die Java Virtual Machine entpackt, wird das Integer
a NullPointerException
ausgelöst. Dies geschieht, weil die JVM versucht, die Funktion aufzurufen null.intValue()
, null
was das Ergebnis einer Autobox ist.
Meiner Meinung nach (und da meine Meinung nicht in der Java-Sprachspezifikation enthalten ist, werden viele Leute es sowieso falsch finden) leistet der Compiler schlechte Arbeit bei der Bewertung des Ausdrucks in Ihrer Frage. Vorausgesetzt, Sie haben geschrieben, sollte true ? param1 : param2
der Compiler sofort bestimmen, dass der erste Parameter - null
- zurückgegeben wird, und er sollte einen Compilerfehler erzeugen. Dies ist etwas ähnlich wie beim Schreiben while(true){} etc...
und der Compiler beschwert sich über den Code unter der Schleife und kennzeichnet ihn mit Unreachable Statements
.
Dein zweiter Fall ist ziemlich einfach und diese Antwort ist schon zu lang ...;)
KORREKTUR:
Nach einer weiteren Analyse glaube ich, dass ich zu Unrecht gesagt habe, dass ein null
Wert für alles eingerahmt / autoboxed werden kann. Wenn wir über die Klasse Integer sprechen, besteht explizites Boxen darin, den new Integer(...)
Konstruktor oder vielleicht das aufzurufen Integer.valueOf(int i);
(ich habe diese Version irgendwo gefunden). Ersteres würde ein werfen NumberFormatException
(und das passiert nicht), während das zweite einfach keinen Sinn ergeben würde, da ein int
nicht sein kann null
...
int foo = (true ? null : 0)
undnew Integer(null)
beide kompilieren gut, wobei die zweite die explizite Form des Autoboxing ist.