For some reason, the following code compiles normally:
public double getSomeDouble() {
return "" != null ? 3.7d : null;
}
I would normally expect Eclipse to mark it as an error (null
can not be turned to a double
primitive).
Just to back my assumption, this code would not work:
public double getSomeDouble() {
return null;
}
Eclipse would mark the return null
line as error, stating:
Type mismatch: cannot convert from
null
todouble
Why doesn't it say the same thing on the previous code snippet?!
It's due to autoboxing and autounboxing. If you look at the bytecode (below), you can see calls to Double.valueOf
(boxing the 3.7d
) and Double#doubleValue
(unboxing the result of the conditional expression). The operands to the conditional operator must be the same type, so the compiler is effectively turning your code into this:
public double getSomeDouble() {
return ("" != null ? Double.valueOf(3.7d) : null).doubleValue();
}
...because Double
is the most specific common type it can find for 3.7d
and null
.
I used a string argument (to eliminate compiler optimization around the invariant expression "" != null
, which the compiler would be able to tell would never be true):
public double getSomeDouble(String str) {
return str != null ? 3.7d : null;
}
which effectively becomes:
public double getSomeDouble(String str) {
return (str != null ? Double.valueOf(3.7d) : null).doubleValue();
}
...and indeed got an NPE at runtime when I passed in null
for str
, when it tried to call doubleValue()
on null
.
Here's the bytecode for my getSomeDouble(String)
(from javap -c MyClass
):
public double getSomeDouble(java.lang.String); Code: 0: aload_1 1: ifnull 13 4: ldc2_w #7 // double 3.7d 7: invokestatic #9 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double; 10: goto 14 13: aconst_null 14: invokevirtual #10 // Method java/lang/Double.doubleValue:()D 17: dreturn
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With