21

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 to double

Why doesn't it say the same thing on the previous code snippet?!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Maxim Rahlis
  • 843
  • 9
  • 26

1 Answers1

23

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
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 4
    Though the error reason is clear now, I still would like to setup eclipse compiler to track those for me not (in runtime that is too late :(), do you know of a way? – Maxim Rahlis Apr 14 '15 at 10:47
  • @MaximRahlis: I'm afraid I don't. Looks like Guillaume has found a feature request you might want to watch... – T.J. Crowder Apr 14 '15 at 18:10
  • Thank you guys! Will certainly watch the eclipse feature request thread. – Maxim Rahlis Apr 14 '15 at 19:41