Method overloading can be done by changing:
The number of parameters in two methods.
The data types of the parameters of methods.
The Order of the parameters of methods.
The compiler does not consider the return type while differentiating the overloaded method. But you cannot declare two methods with the same signature and different return type. It will throw a compile time error.
If both methods have same parameter types, but different return type, then it is not possible.
Can we overload static methods?
The answer is ‘Yes’. We can have two ore more static methods with same name, but differences in input parameters. For example, consider the following Java program.
Method overloading and null error in Java
public class Test
{
// Overloaded methods
public void fun(Integer i)
{
System.out.println("fun(Integer ) ");
}
public void fun(String name)
{
System.out.println("fun(String ) ");
}
// Driver code
public static void main(String [] args)
{
Test mv = new Test();
// This line causes error
mv.fun(null);
}
}
Output :
22: error: reference to fun is ambiguous
mv.fun(null);
^
both method fun(Integer) in Test and method fun(String) in Test match
1 erro
The reason why we get compile time error in the above scenario is, here the method arguments Integer and String both are not primitive data types in Java. That means they accept null values. When we pass a null value to the method1 the compiler gets confused which method it has to select, as both are accepting the null.
This compile time error wouldn’t happen unless we intentionally pass null value. For example see the below scenario which we follow generally while coding.
public class Test
{
// Overloaded methods
public void fun(Integer i)
{
System.out.println("fun(Integer ) ");
}
public void fun(String name)
{
System.out.println("fun(String ) ");
}
// Driver code
public static void main(String [] args)
{
Test mv = new Test();
Integer arg = null;
// No compiler error
mv.fun(arg);
}
}
Output :
fun(Integer )
In the above scenario if the “arg” value is null due to the result of the expression, then the null value is passed to method1. Here we wouldn’t get compile time error because we are specifying that the argument is of type Integer, hence the compiler selects the method1(Integer i) and will execute the code inside that.
Note: This problem wouldn’t persist when the overriden method arguments are primitive data type. Because the compiler will select the most suitable method and executes it.
In the case of overloading if there is no method with the required argument then the compiler won’t raise immediately compile time error. First it will promote arguments to next level and checks is there any matched method with promoted arguments, if there is no such method compiler will promote the argument to the next level and checks for the matched method. After all possible promotions still the compiler unable to find the matched method then it raises compile time error.
The following is the list of all possible Automatic promotion.
In the case of overloading the more specific version will get the chance first.
package com.agreeya.utils;
public class OOConcept {
public void m1(String s) {
System.out.println("String Version");
}
public void m1(Object o) {
System.out.println("Object Version");
}
public static void main(String arg[]) {
OOConcept t = new OOConcept();
t.m1("raju");
t.m1(new Object());
t.m1(null);
}
}
The number of parameters in two methods.
The data types of the parameters of methods.
The Order of the parameters of methods.
The compiler does not consider the return type while differentiating the overloaded method. But you cannot declare two methods with the same signature and different return type. It will throw a compile time error.
If both methods have same parameter types, but different return type, then it is not possible.
Can we overload static methods?
The answer is ‘Yes’. We can have two ore more static methods with same name, but differences in input parameters. For example, consider the following Java program.
Method overloading and null error in Java
public class Test
{
// Overloaded methods
public void fun(Integer i)
{
System.out.println("fun(Integer ) ");
}
public void fun(String name)
{
System.out.println("fun(String ) ");
}
// Driver code
public static void main(String [] args)
{
Test mv = new Test();
// This line causes error
mv.fun(null);
}
}
Output :
22: error: reference to fun is ambiguous
mv.fun(null);
^
both method fun(Integer) in Test and method fun(String) in Test match
1 erro
The reason why we get compile time error in the above scenario is, here the method arguments Integer and String both are not primitive data types in Java. That means they accept null values. When we pass a null value to the method1 the compiler gets confused which method it has to select, as both are accepting the null.
This compile time error wouldn’t happen unless we intentionally pass null value. For example see the below scenario which we follow generally while coding.
public class Test
{
// Overloaded methods
public void fun(Integer i)
{
System.out.println("fun(Integer ) ");
}
public void fun(String name)
{
System.out.println("fun(String ) ");
}
// Driver code
public static void main(String [] args)
{
Test mv = new Test();
Integer arg = null;
// No compiler error
mv.fun(arg);
}
}
Output :
fun(Integer )
In the above scenario if the “arg” value is null due to the result of the expression, then the null value is passed to method1. Here we wouldn’t get compile time error because we are specifying that the argument is of type Integer, hence the compiler selects the method1(Integer i) and will execute the code inside that.
Note: This problem wouldn’t persist when the overriden method arguments are primitive data type. Because the compiler will select the most suitable method and executes it.
In the case of overloading if there is no method with the required argument then the compiler won’t raise immediately compile time error. First it will promote arguments to next level and checks is there any matched method with promoted arguments, if there is no such method compiler will promote the argument to the next level and checks for the matched method. After all possible promotions still the compiler unable to find the matched method then it raises compile time error.
The following is the list of all possible Automatic promotion.
In the case of overloading the more specific version will get the chance first.
package com.agreeya.utils;
public class OOConcept {
public void m1(String s) {
System.out.println("String Version");
}
public void m1(Object o) {
System.out.println("Object Version");
}
public static void main(String arg[]) {
OOConcept t = new OOConcept();
t.m1("raju");
t.m1(new Object());
t.m1(null);
}
}
String Version
Object Version
String Version
package com.agreeya.utils;
public class OOConcept {
public void m1(String s) {
System.out.println("String Version");
}
public void m1(StringBuffer sb) {
System.out.println("StringVersion");
}
public static void main(String arg[]) {
OOConcept t = new OOConcept();
t.m1("raju"); - > String Version // when the next line is commented
t.m1(null); -> Compilation Error
}
}
Note:- we can define a single method which can be applicable for any type of primitive argument, as
follows
m1(double d)
By automatic promotion instead of double we can give char, byte, short, int, long, float, double.
Based on the same approach square root method in math class is declared.
public static double sqrt(double d)
If we want to declare a method which can be applicable for byte, short, char, int, long we should declare as
follows.
m1(long)
public void m1(int i, float f)
{
System.out.println("int, float");
}
public void m1(float f, int i)
{
System.out.println("float, int");
}
public static void main(String arg[])
{
Test t = new Test();
t.m1(10.5f, 10);
t.m1(10, 10.5f);
t.m1(10, 10); // C.E : reference to m1() is ambiguous
t.m1(10.5f, 10.5f);// C.E : can’t find symbol method m1(float,float)
}
class Animal
{
}
class Monkey extends Animal
{
}
class Test
{
public void m1(Animal a)
{
System.out.println("Animal Version");
}
public void m1(Monkey m)
{
System.out.println("Monkey Version");
}
public static void main(String arg[])
{
Test t = new Test();
Case1: Animal a = new Animal();
t.m1(a); //Animal Version
Case2: Monkey m = new Monkey();
t.m1(m); //Monkey Version
Case3: Animal a1 = new Monkey();
t.m1(a1); //Animal Version
}
}
Overloading method resolution will always take care by compiler based on the reference type but not based on runtime object.
Note: In case of wrapper classes, wither it should be exact match or the parent class should match. It means Short is not compatible with Interger, but both are compatible with Number class and Object Class.
1. Primitive Widening > Boxing > Varargs.
2. Widening and Boxing (WB) not allowed.
3. Boxing and Widening (BW) allowed.
4. While overloading, Widening + vararg and Boxing + vararg can only be used in a mutually exclusive manner i.e. not together.
5. Widening between wrapper classes not allowed
Method Overloading with Autoboxing and Widening in Java
Method Overloading with Autoboxing
// Java program to illustrate
// Autoboxing
// while resolving data type as:
// a)reference b)primitive
import java.io.*;
public class Conversion
{
// 1.overloaded method with primitive formal argument
public void method(int i)
{
System.out.println("Primitive type int formal argument :" + i);
}
// overloaded method with reference formal argument
public void method(Integer i)
{
System.out.println("Reference type Integer formal argument :" + i);
}
// 2. overloaded method primitive formal argument
// and to be invoked for wrapper Object as overloaded method
// with wrapper object of same(Long) type as an argument is not
// available.
public void method(long i)
{
System.out.println("Primitive type long formal argument :" + i);
}
}
class GFG
{
public static void main (String[] args)
{
Conversion c = new Conversion();
// invoking the method with different signature.
c.method(10);
c.method(new Integer(15));
c.method(new Long(100));
// Using short will give, argument mismatch;
// possible lossy conversion from int to short
// c.method(new Short(15));
}
}
Output:
Primitive type int formal argument :10
Reference type Integer formal argument :15
Primitive type long formal argument :100
Method Overloading with Widening
// Java program to illustrate method
// overloading
// in case of widening
import java.io.*;
public class Conversion
{
// overloaded method
public void method(int i)
{
System.out.println("Primitive type int formal argument :" + i);
}
// overloaded method primitive formal argument
// and to be invoked for wrapper Object as
public void method(float i)
{
System.out.println("Primitive type float formal argument :" + i);
}
}
class GFG
{
public static void main (String[] args)
{
Conversion c = new Conversion();
// invoking the method with signature
// has widened data type
c.method(10);
c.method(new Long(100));
}
}
Output:
Primitive type int formal argument :10
Primitive type float formal argument :100.0
Method Overloading with Widening and Boxing Together
Widening of primitive type has taken priority over boxing and var-args. But widening and boxing of primitive type can not work together.
// Java program to illustrate method
// overloading for widening
// and autoboxing together
import java.io.*;
public class Conversion
{
// overloaded method with reference type formal argument
public void method(Integer a)
{
System.out.println("Primitive type byte formal argument :" + a);
}
}
class GFG
{
public static void main (String[] args)
{
Conversion c = new Conversion();
// invoking the method
byte val = 5;
c.method(val);
}
}
Output:
25: error: incompatible types: byte cannot be converted to Integer
c.method(val);
^
Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
But boxing followed by widening is acceptable if this is passed to a reference of type Object. See the following example for this.
// Java program to illustrate
// autoboxing followed by
// widening in reference type
// variables
import java.io.*;
public class Conversion
{
// overloaded method with reference type
// formal argument
public void method(Object b)
{
// Object b is typecasted to Byte and then printed
Byte bt = (Byte) b;
System.out.println("reference type formal argument :" + bt);
}
}
class GFG
{
public static void main (String[] args)
{
Conversion c = new Conversion();
byte val = 5;
// b is first widened to Byte
// and then Byte is passed to Object.
c.method(val);
}
}
Primitive type byte formal argument :5
Method Overloading with Var-args argument
Widening of primitive type gets more priority over var-args.
// Java program to illustrate
// method overloading for var-args
// and widening concept together
import java.io.*;
public class Conversion
{
// overloaded method primitive(byte) var-args formal argument
public void method(byte... a)
{
System.out.println("Primitive type byte formal argument :" + a);
}
// overloaded method primitive(int) formal arguments
public void method(long a, long b)
{
System.out.println("Widening type long formal argument :" + a);
}
}
class GFG
{
public static void main (String[] args)
{
Conversion c = new Conversion();
// invokes the method having widening
// primitive type parameters.
byte val = 5;
c.method(val,val);
}
}
No comments:
Post a Comment