What is overloading
Overloading means creating with the same name but different arguments.
Arguments may differ in number or types.
Either methods or constructors can be overloaded in java.
Method overloading means creating different methods with the same name but with different number or type of arguments.
Return type of overloaded methods may be same or different, doesn’t matter.
Only thing that makes methods overloaded is their argument list.
Thus, following points should be remembered for overloaded methods.
- Overloaded methods MUST have different number or type of arguments.
- Overloaded methods CAN have different access modifiers. That is, it is legal for one method to be
private
while other method to beprotected
. - Overloaded methods CAN throw different exceptions.
- Overloaded methods CAN have different return types.
Two overloaded methods can return aString
and anInteger
.
Benefits of method overloading
Overloaded methods are suitable in below scenarios
- When creating an application, method names should be meaningful and indicate the purpose of the method.
Often, more than a single method perform the same function and thus should have the same name. Method overloading makes it possible. - Further, for large methods, it often makes sense to break them into more than one where second method is provided required arguments making it
private
since it is required for internal use only.
Both the methods perform the same function, it is sensible to give same name to both of them.
Method overloading example
Below program demonstrates method overloading where 4 methods are created with same name but with different number or type of arguments.
public class OverloadDemo { // 2 argument method public void printDetails(String name, int rollNo) { System.out.println("Name: " + name + ", Roll No.: " + rollNo); } // single int argument method public void printDetails(int rollNo) { System.out.println("Roll No.: " + rollNo); } // single String argument method public void printDetails(String name) { System.out.println("Name: " + name); } // 3 argument method public void printDetails(String name, int rollNo, String class) { System.out.println("Name: " + name + ", Class: " + class + ", Roll No.: " + rollNo); } public static void main(String[] args) { OverloadDemo obj = new OverloadDemo(); // call one argument string method obj.printDetails("John"); // call one argument int method obj.printDetails(56); // call 3 argument method obj.printDetails("John", 56, "10th"); // call 2 argument method obj.printDetails("John", 56); } }
Above program produces the following output
Name: John
Roll No.: 56
Name: John, Class: 10th, Roll No.: 56
Name: John, Roll No.: 56
Method overloading and Widening
Suppose there are two overloaded methods, one accepting an int
and other a long
and you call this method with 5 as argument.
Which method should be invoked?
When there are two overloaded methods, one accepting a smaller data type and other accepting a bigger one, then first the exact matching method will be found and called.
If the exact match could not be found, then the method accepting next higher data type is invoked.
Example,
public class OverloadDemo { public void wideningOverload(int a) { System.out.println("int"); } public void wideningOverload(long a) { System.out.println("long"); } public void wideningOverload(double a) { System.out.println("double"); } public static void main(String[] args) { new OverloadDemo().wideningOverload(10); } }
Above program contains three overloaded methods each accepting an int
, long
and double
respectively.
This method is called passing it 10 as argument and it prints int.
This is because 10 is an integer and first method is an exact match.
If the first method is removed, then it will print long, since out of long and double, long is the closest match.
Below table briefly explains the widening flow that is applicable.
Argument Type while calling | Argument match | Explanation |
---|---|---|
byte | short , int , long , float , double | If a method with byte argument is not found, then the method with argument as given in the previous column will be matched in the same order. |
short | int , long , float , double | If a method with short argument is not found, then the method with argument as given in the previous column will be matched in the same order. |
int | long , float , double | If a method with int argument is not found, then the method with argument as given in the previous column will be matched in the same order. |
long | float , double | If a method with long argument is not found, then the method with argument as given in the previous column will be matched in the same order. |
float | double | If a method with float argument is not found, then the method accepting a double argument is matched. |
double | No matching data types | If a method with double argument is not found, then a compiler error will be raised when trying to call the method. |
char | int , long , float , double | If a method with char argument is not found, then the method with argument as given in the previous column will be matched in the same order. |
Widening also applies to objects.
That is, if there is a method accepting a super class as argument, then it can be called passing it an object of its sub-type as argument.
Example,
public class OverloadDemo { // method accepting a super class public void wideningOverload(Animal a) { System.out.println("Animal"); } public static void main(String[] args) { // create object of child class Dog dog = new Dog(); new OverloadDemo().wideningOverload(dog); // allowed } }
where Dog is the child class of Animal.
Suppose there are two overloaded methods, one accepting a primitive type and other its wrapper class.
Example, an int
and java.lang.Integer
and you call this method with 10 as argument. Which method should be invoked?
Answer is again exact match.
In this case, since method accepting int
argument exactly matches, it will be called.
Now, suppose there are again two methods, one accepting long
and another a java.lang.Integer
.
In this case, method with long
argument will be called.
This is because when there are options of widening and Boxing, then widening will be preferred.
Thus, in this case 10 can be widened to a long
, hence method with long
argument is executed.
Ambiguous method error in overloading
As mentioned above, which overloaded methods to invoke is decided on the basis of values provided while invoking the method.
There are times when the compiler is unable to determine which method to invoke after looking at the value supplied probably because the values match with arguments of more than one methods.
In such cases, it raises an ambiguous method error.
Typical scenario is
public class OverloadDemo { public void printNumber(Double number) { System.out.println("Double"); } public void printNumber(Integer number) { System.out.println("Integer"); } public static void main(String[] args) { new OverloadDemo().printNumber(null); } }
Above class contains two overloaded methods: one accepts a java.lang.Integer
and another accepts a java.lang.Double
as argument.
While invoking this method with null value, the compiler cannot determine which method to call since both methods can be called with this and it raises an error
OverloadDemo.java:13: error: reference to printNumber is ambiguous
new OverloadDemo().printNumber(null);
^
both method printNumber(Double) in OverloadDemo and method printNumber(Integer) in OverloadDemo match
1 error
In order to resolve the above error, we need to tell the type of value we are supplying while calling an overloaded method.
Thus, instead of passing null
directly, if we assign it some type, then compiler will be able to identify which method to invoke.
Consider modified code below.
public class OverloadDemo { public void printNumber(Double number) { System.out.println("Double"); } public void printNumber(Integer number) { System.out.println("Integer"); } public static void main(String[] args) { // create a variable of type Double // and initialize it to null Double number = null; // supply it as method argument new OverloadDemo().printNumber(number); // prints Double } }
Now the compiler knows that it needs to call the method which accepts a java.lang.Double
argument and the error goes away.
Can we overload main method
The answer is yes.
Main method can also be overloaded.
You can create multiple methods with name main accepting different argument types or numbers or both in a class.
Thus, below program is perfectly legal.
public class OverloadDemo { public void main(long a) { System.out.println("long"); } public void main(double a) { System.out.println("double"); } public static void main(String[] args) { new OverloadDemo().main(10); } }
But remember, when the program is executed, JVM will always look for a main method which is public
, static
, void
and which accepts a java.lang.String
array.
Can we overload static methods
Yes.
static
methods can also be overloaded just like instance methods. Same rules and invoking logic applies to them also.
But you can not create a static
and a non-static method with the same name and same number and type of arguments in a class.
Thus, below code will be a compiler error.
public class OverloadDemo { public static void wideningOverload(int a) { System.out.println("int"); } public void wideningOverload(int a) { System.out.println("long"); } }
Constructor overloading in java
Just as we can overload methods in a class, constructors can also be overloaded.
This makes sense since constructors are also methods with name same as the class name.
Example,
public class OverloadDemo { // default constructor public OverloadDemo () { System.out.println("No-arg constructor"); } // constructor with int argument public OverloadDemo (int a) { System.out.println("int argument constructor"); } // constructor with double argument public OverloadDemo (double a) { System.out.println("long argument constructor"); } public static void main(String[] args) { // create objects new OverloadDemo(); new OverloadDemo(10); new OverloadDemo(20.5); } }
Above code calls constructors as per the arguments supplied while creating objects and produces the below output.
No-arg constructor
int argument constructor
long argument constructor
Operator overloading in java
Java does not support operator overloading as allowed in other languages such as C++.