I have a pair of classes ClassA & ClassB as shown below.
case 1:
class ClassA<T extends Number>{
void method(T t){}
}
class ClassB extends ClassA<Integer>{
@Override
void method(Integer i){}
}
case 2:
class ClassA{
void method(Number t){}
}
class ClassB extends ClassA{
@Override
void method(Integer i){}
}
I have two questions here.
[q1] Am I right if I say that, case2 is the runtime representation of case1(after type erasure)?
[q2] If I am right about [q1], then why the case1 is accepted as a valid override? (I know why case2 is not a valid override since the parameters are not same.)
Someone please shed some light on this. Thanks in advance.
The answer to [q1] is no. The compiler will generate a bridge method in the ClassB
that will actually overide the method(Number)
.
class ClassB extends ClassA{
// bridge method
void method(Number i){
method((Integer)i);
}
void method(Integer i){}
}
You will have the complete answer in the java doc on type erasure.
In Java (since version 5) the return types of an overridden methods have to be covariant and the parameters of the overridden methods have to be contravariant.
That means that the overriding class can be more specific in what it returns and more accepting in what it receives.
In your 2nd example imagine a variable of the type ClassA
with an instance of the ClassB
as a value.
ClassA a = new ClassB(); // This is legal, since ClassB is a subclass of ClassA
a.method(1.0); // This is legal, since ClassA.method accepts Number
The other way however would be ok:
public class ClassC { public Number method(Integer i) {...} }
public class ClassD extends ClassC {
@Override
public Integer method(Number n) {...}
}
is valid, because the ClassD
still fulfills the contract defined by ClassC
.
The actual superclass of ClassB
is ClassA<Integer>
. Therefor its member function method
has the compile-time signature:
void method(Integer t){}
You can convince yourself by invoking something like
ClassA a = new ClassB();
a.method(1.0);
You should see a runtime error. In fact it is only possible to compile this, because I used the erased version of ClassA
. In fact every assignment to a generic type other than ClassA<Integer>
(eg ClassA<Number
>) would fail due to incompatible types.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.