public class WrapperClasses{
void overloadedMethod(Number N){
System.out.println("Number Class Type");
}
void overloadedMethod(Double D){
System.out.println("Double Wrapper Class Type");
}
void overloadedMethod(Long L){
System.out.println("Long Wrapper Class Type");
}
public static void main(String[] args){
int i = 21;
WrapperClasses wr = new WrapperClasses();
//wr.overloadedMethod(i);
}
}
class mine extends WrapperClasses{
void overloadedMethod(int N){
System.out.println("Integer Class Type");
}
public static void main(String[] args){
int i = 21;
WrapperClasses wr = new mine();
wr.overloadedMethod(i);
}
}
This prints Number Class Type
.
I understand the rules of wrapper class method overloading:
According to rule 1, it should print Integer Class Type
. What am I missing here?
At a language spec level, it is because methods with parameters which differ as being primitive and wrapped primitive types are not considered as override-equivalent. (A fancy way of saying "they just don't because the language spec says so").
But logically, they shouldn't either, at least in the case of an int
parameter in a subclass "overriding" a wrapped parameter in a superclass.
By Liskov's Substitution Principle, methods in subclasses must accept at least all the parameters accepted by the method in the superclass.
If the superclass method accepts the wrapped class, it can accept null
. If the subclass method were allowed only to accept int
, it could not accept null, so it would not be substitutable.
Method overload resolution is determined at compile time, based on the compile time type of the variable holding the reference to the instance for which you are calling the method.
void overloadedMethod(int N)
is only defined in the sub-class mine
. Therefore, when you call a method on a reference whose type is the base class WrapperClasses
, only the methods of the base class can be considered for overload resolution.
The int
argument that you pass to the method doesn't match any of the 3 methods of the base class, but after it is boxed to Integer
, it matches the void overloadedMethod(Number N)
method.
If you change your code to
int i = 21;
mine wr = new mine();
wr.overloadedMethod(i);
it will execute void overloadedMethod(int N)
.
Polymorphism is performed by the JVM at runtime. For this to work, the two methods must have the same runtime signature.
In the case of covariant return types, the compiler generates bridge methods to allow this to happen, however, the Java language Spec doesn't require such a bridge method for wrappers vs primitives.
There is a number of reasons this might be, however the most likely is backward compatibility. Java 1.0 didn't do this, and even though autoboxing was added more than a decade later, this wasn't allowed to break older code. i.e. wrapper and primitives overloaded each other, not overrode, so they can't now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With