java tech
Ram Patra Published on June 2, 2019

Reusing the same method name in the same class or subclass but with different arguments (and optionally, a different return type) is called Method Overloading in Java.

There are certain rules for overloading, the below code points out all of the rules:

In short, the only rule you MUST obey is to change the argument list of the overloaded method, the rest are all optional.

The output of the above program is:

In the Animal version
In the Horse version
In the Animal version


Notice the call doStuff(animalRefToHorse), here the Animal version of doStuff() is called despite the actual object being passed is of a Horse. The reference type (not the object type) determines which overloaded method is invoked.

To summarize, which overridden version of the method to call (in other words, from which class in the inheritance tree) is decided at runtime based on object type, but which overloaded version of the method to call is based on the reference type of the argument passed at compile time.

Therefore, polymorphism doesn’t determine which overloaded version is called, polymorphism does come into play when the decision is about which overridden version of a method is called.

I will show you different scenarios after which you can answer any question related to method matching (which method will be invoked).

The 3 factors that can make overloading a little tricky (written in order of preference):

• Widening
• Autoboxing
• Var-args

The output of the above program is float float float float int,int Long,Long.

From the output it is clear that the JVM prefers widening over autoboxing and var-args. In every case, when an exact match isn’t found, the JVM uses the method with the smallest argument that is wider than the parameter.

Now look at the call go(l, l) at last, this invokes go(Long x, Long y) rather than go(long... x) which clearly shows JVM prefers boxing over var-args.

Widening reference variables

Reference widening depends on inheritance, in other words if it passes the IS-A test then no harm. Consider the below code:

The above code compiles fine as Dog can widen into an Animal because it passes the IS-A test. If in case, Dog didn’t have extended Animal then widening wouldn’t be possible and the code wouldn’t compile.

Similarly, you cannot widen Integer to Long but you can widen int to long.

Combine Widening with Boxing

Let’s see what happens when the compiler has to widen and then autobox the parameter for a match to be made.

The above program fails to compile, the JVM does not widen and then box. It may be because widening existed in the earlier versions of Java and it wanted a method that is invoked via widening shouldn’t lose out to a newly created method that relies on boxing. In other words, Java designers wanted the preexisting code should function the way it used to.

Now imagine if JVM tried to box first, the byte would have been converted to a Byte. Now we’re back to trying to widen a Byte to a Long, and of course, the IS-A test fails.

So both of the ways didn’t work.

Now let’s see another program when the compiler has to autobox and then widen the parameter for a proper match.

The above code compiles and produces the output 5. Firstly, the byte b was boxed to a Byte. And then the Byte reference was widened to an Object (since Byte extends Object). So, the go() method got an Object reference that actually refers to a Byte object.

From the above 2 examples its certain that the JVM can never widen and then box but can box and then widen.

Combine both Widening and Boxing with Var-args

The above code compiles fine and produces the output:

long...
Integer...
Object...


From the result, its clear that we can successfully combine var-args with either widening or boxing.

### Q&A

Q1. Consider the below program in which a method is both overridden and overloaded.

Figure out which version of eat() will run on each of the invocation made?

A. Animal ah = new Horse();
ah.eat();
B. Horse he = new Horse();
he.eat("Apples");
C. Animal a2 = new Animal();
a2.eat("treats");
D. Animal ah2 = new Horse();
ah2.eat("Carrots");


Ram Patra Published on June 2, 2019