CodeGym/Java Course/Java Core/Overloading methods | part 2

Overloading methods | part 2

Available

"Hello, Amigo! A couple of days ago I told you about overloading methods. Did you understand everything?"

"Yes. I remember. Each class method must be unique. A member method is unique if the class has no other method with the same name and parameter types (and the order of the parameters matters)."

"Very good! I see you've learned that lesson well. Today I want to expand your knowledge in this topic just a bit. What method do you think will be called in each case?"

Code
class Cat
{
 public static void print(int n)
 {
  System.out.println(n);
 }
 public static void print(short n)
 {
  System.out.println(n);
 }
 public static void print(Integer n)
 {
  System.out.println(n);
 }
 public static void print(String s)
 {
  System.out.println(s);
 }
public static void main(String[] args)
{
  Cat.print(1);
  Cat.print((byte)1);
  Cat.print("1");
  Cat.print(null);
 }
}

"It's hard to say."

"In the first case, 1 is an int. We have a 100% match with the method that takes an int. The first void print(int n). will be called.

In the second case, we don't have a method that takes a byte. But there are two methods that take a short and an int. Based on type widening rules, a byte will first be widened to a short, and then widened to an int. Thus, the verdict is that the void print(short n). will be called.

In the third case, we have a 100% match with the method that takes a String. The void print(String s). method will be called.

The fourth case is ambiguous. null doesn't have a specific type. The compiler will refuse to compile this code. In this case, we need to write Cat.print((Integer)null) to call the third method and Cat.print((String)null) to call the fourth."

"That was very informative. Thank you."

"I'd like to point out that when determining the correct method to call, types can only widen. They cannot narrow. Consider this example:"

Code
class Cat
{
 public static void print(short n)
 {
  System.out.println(n);
 }
 public static void print(Integer n)
 {
  System.out.println(n);
 }

 public static void main(String[] args)
 {
  Cat.print((byte)1);
  Cat.print(1);
 }
}

In the first case, the byte type will be widened to a short and the first method will be called: void print(short n)..

In the second case, there will be an implicit widening conversion from int to Integer, and then the second method will be called: void print(Integer n)..

"I didn't expect that."

"No, here's the real surprise:"

Java code Description
class Cat
{
 public static void print(Object o)
 {
  System.out.println(o);
 }
 public static void print(String s)
 {
  System.out.println(s);
 }

 public static void main(String[] args)
 {
  Cat.print(1);
  Cat.print(null);
 }
}
In the first case, int will be extended to Integer. Because there is no method for Integer, the most suitable method (and the one called) is void print(Object o)

In the second case, there won't be any compilation errors and void print(String s) will be called, which is somewhat not obvious.

"Amigo, I hope you understand that in such cases it's best to specify a type cast operator (as in we did with «(byte)») in order to know exactly which method will be called."

"I never expected any problems would come from overloading methods. But then you come along. Thanks, Rishi. I'll keep up my guard on this point."

Comments (18)
  • Popular
  • New
  • Old
You must be signed in to leave a comment
Gellert Varga
Level 23 , Szekesfehervar, Hungary
7 March 2021, 18:29
In the last example, why doesn't Cat.print(null) cause a compiler error, and why don't we need to cast the "null" to a String or Object type before we send it to the methods? Even though both the print(Object o) and print(String s) methods would be able to receive the null reference. Answer: String is a descendant of Object, and in this case the JVM is able to decide which method to use. JVM chooses the one that is under the other one on the chain of inheritance. Which requires the fewest widening conversions.
DarthGizka
Level 24 , Wittenberg, Germany
4 June 2021, 17:49
This is one more dark corner where Java is even more of a hash than C# itself! (But not to worry, in a few cases - like covariant return - Java is actually ahead instead of muddling behind.) ;-)
Gellert Varga
Level 23 , Szekesfehervar, Hungary
4 June 2021, 20:58
Unfortunately I don't have any basis for comparison, I don't know C# and I don't know other ones... (and I think I don't want to know any other languages for the time being; learning this one also will be more than enough work for me in the coming years...)
Anonymous #11416402
Level 24 , China
20 October 2024, 01:30
Thanks for your explanation!! I really appreciate it🥰
Agent Smith
Level 38
28 August 2020, 15:17
Good lesson, today I learned.
Nicola
Level 17 , Vienna, Austria
27 October 2019, 17:25
I don't gent the last example. If type can only widen, why Cat.print(1) call void print(Object o)?
Fadi Alsaidi
Level 34 , Carrollton, TX, USA
25 January 2020, 01:58
Because Integers can fit into Objects so it is widened
Chang You
Level 47 , Santa Rosa, United States
25 December 2020, 14:40
Object > Integer
15 August 2019, 21:40
my head's exploding in 3... 2... 1...
Ed Maphis
Level 20 , Painesville, United States
5 June 2019, 22:29
You probably shouldn't write programs the rely on this behavour.
Kron1K
Level 26 , AUS, Australia
13 June 2019, 14:13
I have a "mentor" with over 20 year experience in java and he says that 99% of the time this can be easily avoided and usually means the code is not written well. Its not something you should encounter alot.
John
Level 17 , Mansfield, Philippines
13 June 2021, 06:47
i hope i have a mentor too..
Darko Jakimovski
Level 18 , Kriva Palanka, Macedonia, The Former Yugoslav Republic of
15 May 2019, 10:21
I don't understand why in the first case it's an error to call the method with a "null" as a parameter and in the second case it doesn't :/ It's the same thing
robin
Level 23 , Lublin, Poland
16 May 2019, 12:12
It seems to be a matter of specificity. See the explanation I found on stackoverflow
Darko Jakimovski
Level 18 , Kriva Palanka, Macedonia, The Former Yugoslav Republic of
16 May 2019, 15:18
Thanks robin, that cleared things up a bit for me
Oregano
Level 24 , Warsaw, Poland
22 January 2020, 07:53
So it seems that in the last example, both methods can take null but Object is super-type of String and Java will choose the more specific type - in this case, String. In the first example, both Integer and String could take null and they have both the same level of specificity - Java don't know which one to choose what causes an error
Kent Hervey Software Engineer/Consult Expert
26 March 2021, 16:23
From the Stackoverflow: the ambiguity in the first example is the problem. The second example does not have the ambiguity.
Tayyab Mubeen
Level 16 , Lahore, Pakistan
12 November 2018, 17:11
Type cast is necessary when we are doing method overloading...!!!