Auto-Unboxing benötigt ternäres if-else

23

Dieser Code funktioniert gut: -

    Integer nullInt = null;
    if (1 <= 3) {
        Integer secondNull = nullInt;
    } else {
        Integer secondNull = -1;
    }
    System.out.println("done");

Dies löst jedoch eine Nullzeigerausnahme aus, während Eclipse warnt, dass ein automatisches Entpacken erforderlich ist: -

    Integer nullInt = null;
    Integer secondNull = 1 <= 3 ? nullInt : -1;
    System.out.println("done");

Warum ist das so, kann jemand bitte führen?

91StarSky
quelle

Antworten:

22

Der Typ des ternären bedingten Ausdrucks

1 <= 3 ? nullInt : -1

is int(das JLS enthält mehrere Tabellen, die den Typ des ternären bedingten Operators in Abhängigkeit von den Typen des 2. und 3. Operanden beschreiben).

Wenn es versucht, eine Box nullIntzu entpacken int, NullPointerExceptionwird a ausgelöst.

Um das Verhalten Ihres if-else-Snippets zu erhalten, müssen Sie Folgendes schreiben:

1 <= 3 ? nullInt : Integer.valueOf(-1)

Jetzt ist der Typ des Ausdrucks so Integer, dass kein Unboxing stattfindet.

Eran
quelle
4
Um
3

Ich bin mir ziemlich sicher, dass Argumente für ternäre Operatoren vom gleichen Typ sein müssen. Da Sie -1 und einen konstanten nullintCompiler verwenden, versuchen Sie, die Box nullintzu entpacken , um einen Wert zu erhalten. Und dann Autobox es in secondNullVariable zu speichern .

Die Toster
quelle
3

Dies liegt daran ? :, dass eine Unboxing-Konvertierung durchgeführt wird, wenn die beiden Operanden für den bedingten Operator ein primitiver Typ und sein Boxed-Referenztyp sind ( JLS §15.25.2 ):

Der Typ eines numerischen bedingten Ausdrucks wird wie folgt bestimmt:

  • ...
  • Wenn einer der zweiten und dritten Operanden vom primitiven Typ T ist und der Typ des anderen das Ergebnis der Anwendung der Boxkonvertierung (§5.1.7) auf T ist, ist der Typ des bedingten Ausdrucks T.

Im Allgemeinen behält das Ersetzen einer ifAnweisung durch einen ? :Ausdruck nicht immer die Bedeutung des Codes bei, da der ? :Ausdruck selbst einen Typ zur Kompilierungszeit haben muss. Das heißt, wenn die Typen der beiden Operanden unterschiedlich sind, muss eine Konvertierung in einen oder beide durchgeführt werden, damit das Ergebnis einen konsistenten Typ zur Kompilierungszeit hat.

kaya3
quelle
2

Dieser hat funktioniert (in Java 1.8):

Integer secondNull = 1 <= 3 ? null : -1;
Catalina Chircu
quelle