Java method overloading
the following method returns the output: in the primitive method int arg
public class TestMethodOverloading {
private void show(int a){
System.out.println("in primitive int arg method");
}
private void show(float a){
System.out.println("in primitive float arg method");
}
public static void main(String[] args) {
TestMethodOverloading tmo = new TestMethodOverloading();
tmo.show(4);
}
}
If I change the type of the argument of the show method from int to Integer then the output is returned as: in the primitive method float arg
public class TestMethodOverloading {
private void show(Integer a){
System.out.println("in Integer arg method");
}
private void show(float a){
System.out.println("in primitive float arg method");
}
public static void main(String[] args) {
TestMethodOverloading tmo = new TestMethodOverloading();
tmo.show(4);
}
}
But now if I change the argument type of the second method from float to Float, then the output changes to: in the Integer arg method
public class TestMethodOverloading {
private void show(Integer a){
System.out.println("in Integer arg method");
}
private void show(Float a){
System.out.println("in primitive float arg method");
}
public static void main(String[] args) {
TestMethodOverloading tmo = new TestMethodOverloading();
tmo.show(4);
}
}
Can anyone help me understand this behavior
source to share
This is because when trying to find mapping methods to call, Java will look at methods where boxing or unboxing conversion is not required, before it looks at methods where boxing or unboxing conversion is required.
JLS section 15.12.2 states:
- The first phase (§15.12.2.2) performs overload resolution without allowing boxing conversion or unboxing, or using a method call to the arity variable. If no applicable method is found at this stage, processing continues until the second phase .
This ensures that any calls that were valid in the Java programming language prior to Java SE 5.0 are not considered ambiguous as a result of injecting arity variable methods, implicit boxing, and / or unboxing. However, declaring a method on an arity variable (§8.4.1) may change the method chosen to express a method invocation of a given method, since the arity variable method is treated as a fixed arity method in the first phase. For example, declaring m (Object ...) in a class that already declares m (Object) results in m (Object) no longer being selected for some call expressions (such as m (null)) like m (Object [])) is more specific.
- The second phase (§15.12.2.3) performs overload resolution, and allows boxing and unboxing , but still precludes the use of calling the arity variable method. If no applicable method is found at this stage, processing continues until the third phase.
This ensures that the method is never selected by calling the arity variable method if applicable by calling the fixed arity method.
- The third stage (§15.12.2.4) allows you to combine overloading using the arity variable, boxing and unboxing methods.
(bold emphasis mine)
In the first example, the method int
is an exact match and is taken by method float
even if applicable without boxing / unboxing.
In the second example, the method is float
applicable without boxing / unboxing, but the method Integer
requires boxing, so the method is selected float
.
In the third example, both methods require boxing, so the method is now selected Integer
.
source to share