This question goes from my previous post in here.. Before I post my question, I am pasting the contents from oracle docs;
8.4.8.1. Overriding (by Instance Methods)
An instance method m1, declared in class C, overrides another instance method m2, declared in class A iff all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
8.4.2. Method Signature
The signature of a method m1 is a subsignature of the signature of a method m2 if either:
m2 has the same signature as m1, or
the signature of m1 is the same as the erasure (§4.6) of the signature of m2.
My understanding of type erasure
when overriding
is involved is as follows:
if after erasure
, the signature of m1 and m2
are same, then then they are considered overridden
.
so in my previous post above, I tried to override
a parent class method
that takes
List<String>
by a subclass method
that takes List<Integer>
assuming after type erasure
what is left is just List<Object>
. but that is wrong. so my understanding of the above definition
of method overriding
when erasure
is involved is totally wrong. can some give a simple
example to explain the above point.
Thanks. btw the above points come from here.
Whether a method overrides another doesn't just deal with the erasures of the methods. The compiler determines whether a method overrides another, and it has access to the generic type parameters involved before type erasure occurs.
Your thoughts about using erasure to determine overrides are not quite correct. Let's add the following JLS Section, 8.4.8.1, to the discussion:
An instance method m1, declared in class C, overrides another instance method m2, declared in class A iff all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either:
m2 is public, protected, or declared with default access in the same package as C, or
m1 overrides a method m3 (m3 distinct from m1, m3 distinct from m2), such that m3 overrides m2.
It's required that m1
is a subsignature of m2
, but not the other way around.
Example 1:
class A {
public void foo(List<String> list) { }
}
class B extends A {
@Override
public void foo(List list) {}
}
This is legal, because the signature of B
's foo
method is the same as the erasure of A
's foo
method.
Example 2:
class A {
public void foo(List list) { }
}
class B extends A {
@Override
public void foo(List list) {}
}
This is legal, because the signatures are the same (even if they are raw).
Example 3:
class A {
public void foo(List list) { }
}
class B extends A {
@Override
public void foo(List<Integer> list) {}
}
This is not legal, because the erasure of the overriding method is not taken into account. That is, List<Integer>
is compared with the erasure of List
, which is still just List
, and they're not the same.
Example 4:
class A {
public void foo(List<String> list) { }
}
class B extends A {
@Override
public void foo(List<Integer> list) {}
}
This is again not legal, because the erasure of the overriding method is not taken into account. That is, List<Integer>
is compared with the erasure of List<String>
(List
), and they're not the same.
You cannot change the generic type parameters of the parameters in the overriding method (e.g. List<String>
to List<Integer>
. You cannot introduce generics when overriding a method that didn't utilize generics (e.g. (List
to List<Integer>
). However, you can remove generics when overriding (e.g. List<String>
to List
).
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