简体   繁体   中英

Type erasure and overriding generic method

My understanding about generic was that if I have public void saveAll(Collection<? extends Object> stuff) { then compile will determine the "most common type" of the input parameter to be Collection<Object> . Now, with that I wrote below code for overriding the generic methods, but I get following error message in the overriding method - Name clash: The method saveAll(Collection<? extends Object>) of type ChildWithGenericMethod has the same erasure as saveAll(Collection<Object>) of type ParentWithGenericMethod<T> but does not override it

public class ParentWithGenericMethod {
    public void saveAll(Collection<Object> stuff) {

    }
}

public class ChildWithGenericMethod extends ParentWithGenericMethod{
    public void saveAll(Collection<? extends Object> stuff) {

    }
}

What I want to know is that after type erasure how these methods would look like, I thought they would look like public void saveAll(Collection stuff) { and hence I should be able to override, because if I don't use generics then I can override like this.

Please note that I know that I can see the byte code after compilation using "javap" but it doesn't tell me how these methods would look like after "type erasure".


Update:
This question doesn't answer my question, if after type erasure both methods become public void saveAll(Collection stuff) { then why subclass is getting overriding error, because with public void saveAll(Collection<Object> stuff) { it passes the overriding rules.

It's worth remembering run time vs compile-time dispatch.

Take away generics for a second.

public class Parent {
  public void saveAll(Object x) {
  }
}

public class Child extends Parent {
   public void saveAll(String x) {
  }
}

public String x = "hello";
public Object y = new Integer(334);
public Object z = "goodbye";

public Child c1 = new Child();

c1.saveAll(x); // invokes Child.saveAll
c1.saveAll(y); // invokes Parent.saveAll
c1.saveAll(z); // invokes Parent.saveAll even though z contains a String

Now put generics back into the story.

 public class Child<T extends Object> extends Parent {
   public void saveAll(T x) {
  }
}

Here, saveAll overloads, rather than overrides, the parent's saveAll.

replacing T with an anoymous ? doesn't really change that -- the compiler is trying to create a method that overloads the parent's method, but then realizes that it can't dispatch on compile-time type.

[edit, see Lew Block's comment on the original: the compiler needs to decide whether the child method overrides or overloads the parent's method before type erasure]

if after type erasure both methods become public void saveAll(Collection stuff) { then why subclass is getting overriding error, because with public void saveAll(Collection stuff) { it passes the overriding rules.

The problem (again see Lew Bloch's comment) is that overriding is determined before type erasure. Before type erasure, the parent and child method have different signatures, and so the compiler creates them as overloaded methods rather than overriding methods. After type erasure, the compiler realizes it is in a bind because it now has two methods with the same signature and no way to know how to dispatch.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM