Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how does erasure handles overriding scenarios in Java?

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.

like image 395
brain storm Avatar asked Feb 10 '14 23:02

brain storm


1 Answers

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).

like image 117
rgettman Avatar answered Oct 15 '22 05:10

rgettman