11

Consider two overloads:

public void add(Integer value)
{
    add(value == null ? null : value.doubleValue());        
}

and

public void add(Double value)
{
    // some code here
}

If I call the first one with a null instance of an Integer, then does the ternary conditional call the overload to a Double, or does it call itself?

On my machine it calls the Double overload, but is this well-defined Java? And what does the JLS say about this?

radoh
  • 4,554
  • 5
  • 30
  • 45
  • 3
    Have you tried reading the JLS yourself? Seems to me its completely unnecessary to ask what the JLS says when it's available online for free to read yourself. So I suggest that you will find it fruitful to read the JLS yourself. @Fitzwilliam Bennet-Darcy – Lew Bloch Apr 19 '17 at 17:11
  • 1
    Try it yourself! You learn quicker with hands-on experience! – whirlwin Apr 19 '17 at 18:43
  • Related: http://stackoverflow.com/q/43506017/2513200 – Hulk Apr 20 '17 at 08:25

3 Answers3

21

Yes, it's well defined that it will call the Double overload. It couldn't call the Integer overload because there's no implicit conversion from double (which is the type of the conditional expression) to Integer.

Basically, there are two parts of this that are irrelevant:

  • That the method is being called from an overload
  • That the method argument is a conditional expression

So if you think about it as:

Double d = getSomeDoubleValueFromAnywhere();
add(d);

... which method would you expect to be called? Presumably the add(Double) method - so that's what is called in your situation too.

The tricky part is working out the type of the conditional expression - is it Double or double? I believe the rules (which are hard to follow, IMO) mean that it's Double, due to the use of a null literal (which is of the null type). If instead you had:

Double dv = null;
add(value == null ? dv : value.doubleValue()); 

... then the conditional expression type would be double, and you'd get a NullPointerException if value were ever null, because it would be trying to unbox the null value.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thank you very much for the advice, and for fixing one of my very many bugs. – Fitzwilliam Bennet-Darcy Apr 19 '17 at 15:36
  • 1
    @FitzwilliamBennet-Darcy: My mistake - it wasn't a bug! (There are similar situations where it is though... I'm trying to remember the exact case now...) – Jon Skeet Apr 19 '17 at 15:36
  • Thankfully I am terribly forgetful. It's a lovely answer all the same. – Fitzwilliam Bennet-Darcy Apr 19 '17 at 15:37
  • Until I read @Andremoniy's link I could not understand why `null` would be evaluated as a `Double`. Could you please add that to your answer? – Mad Physicist Apr 19 '17 at 15:44
  • Thank you! That is a very good intuitive way to think about it. Here's more fuel for your first million! – Mad Physicist Apr 19 '17 at 15:46
  • 1
    @MadPhysicist: I'm still working on this, as it's not clear whether the type of the conditional expression is actually `double` or `Double`. – Jon Skeet Apr 19 '17 at 15:49
  • Based on the link provided by @Andremoniy, I think there is only one item that applies: `If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.` That means `Double`. – Mad Physicist Apr 19 '17 at 15:53
  • Intuitively, you can't have a `double` set to `null` – Mad Physicist Apr 19 '17 at 15:54
  • @MadPhysicist: Yes, I know that you can't set a `double` to `null`. But the null type *isn't* the result of applying a boxing conversion to `double`. And if it did, it would mean `double`, not `Double` (because `double` is the primitive type). – Jon Skeet Apr 19 '17 at 15:57
  • You are right. Related: http://stackoverflow.com/q/13291117/2988730. Looks like it's `double` after all. – Mad Physicist Apr 19 '17 at 16:03
  • @MadPhysicist: No, it's not, it's `Double` - just like the type of the expression in that related question is `Integer`. – Jon Skeet Apr 19 '17 at 16:04
  • 1
    [Table 15.25-B](http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25) in the JLS says the type of the conditional expression is actually `lub(null,Double)`, where `lub` is some [crazy incomprehensible thing from section 4.10.4](https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.10.4). – user2357112 Apr 19 '17 at 20:43
3

I'm pretty sure that such kind of question was already asked here, but can not find it.

Anyway,

add(value == null ? null : value.doubleValue()); invokes add(Double value), this is very easy to check via trying to compile code w/o second method, and in the debugger.

Regarding what does JLS say about it: type of the expression value == null ? null : value.doubleValue() is obviously Double, how it is described here.

Andremoniy
  • 34,031
  • 20
  • 135
  • 241
  • That is one dense list. Thanks for the link. – Mad Physicist Apr 19 '17 at 15:45
  • You say the type is "obviously `double`" - I'm not sure about that. It's what I originally thought as well, but then that would give a `NullPointerException` if the Integer value were a null reference, and that doesn't seem to happen. I'm still looking into this. – Jon Skeet Apr 19 '17 at 15:50
  • Having worked through it now, I'm pretty sure that the type of the expression really *is* `Double` rather than `double`. – Jon Skeet Apr 19 '17 at 16:00
  • @JonSkeet of course it is `Double` due to autoboxing, this is my terrible misprint, thanks for pointing that – Andremoniy Apr 19 '17 at 16:05
  • 1
    http://stackoverflow.com/questions/8098953/tricky-ternary-operator-in-java-autoboxing – Andremoniy Apr 19 '17 at 16:06
0

Because you are using .doubleValue(), even if it is a whole number, it is still converted to double. Thus is is calling the overload public void add(Double value).

Cardinal System
  • 2,749
  • 3
  • 21
  • 42