-1

I am practicing for an exam, and one of the questions will be about Java overloading on what the output will be. This is the following question.

The Program

The Output is:

1 X:int Y:int Y:int

2: X:Object Y:Integer X:Object

3: X:Double Y:double X:Double

4: X:Double X:Double

I do not understand why 4 is X:Double in both cases and not X:Object. Why in part 3 z.dosmth(0.0) returns X:Double and not Y:double. And similarly why z.dosmth((Integer) 0) is X:Object not Y:Integer in part 2.

Thank you in Advance

SpringLearner
  • 13,738
  • 20
  • 78
  • 116
  • 12
    Don't post code as an image. Please post it as code-formatted text. Read the [tour] and the [help] sections please. – Hovercraft Full Of Eels Jun 16 '16 at 13:49
  • 1
    The rules are detailed in the JLS: http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2 and are very complex. The whole thing is several pages long. In practice, it's much easier than that because decent developers don't overload methods that way and even less call such an overloaded method with null. So, knowing the rule precisely is interesting for someone who wants to implement a compiler/VM, but anyone producing code like the above should just be forbidden to code. – JB Nizet Jun 16 '16 at 13:55
  • 3
    I write Java code for almost 20 years, and I'm not sure I could have answered correctly. I don't think that makes me a bad programmer, though. – JB Nizet Jun 16 '16 at 13:57
  • 1
    Indeed, a good programmer would never have `dosmth(double)` and `dosmth(Double)` methods in the same class. The exam question is an interesting academic exercise, but fairly useless for gauging software engineering skills (unless “I would never do that” is an allowable answer). I can’t help thinking that whoever crafted it was stroking their own ego. – VGR Jun 16 '16 at 14:29

1 Answers1

1

A concise formulation of the rule, which Java follows when figuring out which overload to invoke, would sound something like this:

When there are several overloads, which may be invoked for a given set of parameters, the most specific one is selected.

(You can read a relevant quote from Java Language Specification in this answer.)

It's also important to know that, unlike with virtual method dispatch, overload resolution occurs at compile time, so the only thing Java has to go by when selecting the overload is the type of the reference, through which you invoke the method, not the runtime type of the object, to which said reference points.

With that in mind, let's look at the lines, which surprise you.


z.dosmth((Integer)0); // prints "X:Object"

Pay attention to the type of reference z, through which you are invoking dosmth(). It's X, so the only methods, involved in overload resolution, are the ones declared in class X. As there isn't an overload accepting Integer in X, the only suitable overload, void dosmth(Object obj), gets called.

Yes, we know that actually at run time, z refers to an object of class Y, which does have an overload for Integer, but at compile time there is, in general case, no way for compiler to tell the type of the object, to which z is going to refer in the line z.dosmth((Integer)0), so it's only going to concern itself with overloads, available in class X itself.


z.dosmth(0.0);    // prints "X:Double"

Same reason as the previous case. z is a reference of type X, suitable candidates in X for parameter 0.0 are void dosmth(Double obj) and void dosmth(float obj). 0.0 is a double literal, so Java prefers void dosmth(Double obj). Had it been 0.0f (a float literal), the overload accepting float would've been preferred.


x.dosmth(null);    // prints "X:Double"
z.dosmth(null);    // prints "X:Double"

This is the most interesting case. null is compatible with both Object and Double. Which one is more specific, though? It's Double, ain't it? Therefore, void dosmth(Double obj) gets selected over void dosmth(Object obj).

Community
  • 1
  • 1
TerraPass
  • 1,562
  • 11
  • 21