Seltsame NullPointerException

  • Themenstarter Themenstarter Wangnick
  • Beginndatum Beginndatum
W

Wangnick

Gast
Ich kann mir folgende seltsame NullPointerException nicht erklären:

Java:
Float f1 = false? 1.2f: null;
System.out.println( f1 );
Float f2 = false? 1.2f: false? 2.3f: null;
System.out.println( f2 );

Wieso funktioniert f1 und f2 nicht?
 
f1 funktioniert, weil hier der Compiler erkennt, dass diese Zuweisung immer null ist; er optimiert den ganzen Ausdruck mit dem ternären Operator weg und erzeugt den gleichen Bytecode wie bei
Java:
float f1 = (Float)null;
Bei f2 geht der Compiler mit der Analyse offenbar nicht soweit, dass er auch hier den konstanten Ausdruck erkennen und eliminieren würde.
Setze mal spaßeshalber statt false eine Variable ein, dann passiert auch bei f1 keine Optimierung, und es knallt schon da.
 
Leider nein. Variable oder boolean Konstante macht keinen Unterschied.

Tatsächlich passiert mir das in einem komplexeren Code. Ich hab hier nur soweit möglich vereinfacht.
 
Wenn man dekompiliert, sieht man dass bei f2 ungefähr so etwas entsteht:

Java:
 Float f2 = null.floatValue();
 
Leider nein. Variable oder boolean Konstante macht keinen Unterschied.
Zumindest mit dem JDK 1.6.0_17 unter Windows tut es das.

Auf jeden Fall ist dieses Konstrukt falsch und müsste eigentlich immer eine NPE bringen.

Der Ausdruck <Bedingung> ? 1.0f : null liefert als Ergbnis ein float; der Typ des ersten Operanden bestimmt den Wert des Ausdrucks. Deshalb muss der zweite Parameter auch in einen float gewandelt werden (quasi Auto-Unboxing) - und das geht schief.

//Edit: deswegen funktioniert es auch, wenn man schreibt
Java:
Float f2 = false ? (Float)1.2f: (false? 2.3f: null);
Wenn der erste Operand ein Float ist, dann muss beim zweiten kein Unboxing stattfinden udn alles ist gut.
 
Zuletzt bearbeitet:
Der Ausdruck <Bedingung> ? 1.0f : null liefert als Ergbnis ein float; der Typ des ersten Operanden bestimmt den Wert des Ausdrucks. Deshalb muss der zweite Parameter auch in einen float gewandelt werden (quasi Auto-Unboxing) - und das geht schief.

Nach langspec-3.0 para 15.25 sind beide Wertoperanden gleichwertig. Der Fall wird dort wie folgt beschrieben:
"Otherwise, the second and third operands are of types S1 and S2 respectively. Let T1 be the type that results from applying boxing conversion to S1, and let T2 be the type that results from applying boxing conversion to S2. The type of the conditional expression is the result of applying capture conversion (§5.1.10) to lub(T1, T2) (§15.12.2.7)."

Für false?1.0f:null ist also T1 Float (nach boxing) und T2 der Nulltyp. Was ist dann lub(T1,T2)? Float? Der Nulltyp? Object?

false?1.0f:null evaluiert zu null. Wieso ergibt dann false?1.0f🙁false?1.0f:null) nicht auch null?
 

Neue Themen


Zurück
Oben