本文介绍了类型擦除和覆盖通用方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对泛型的理解是,如果我有public void saveAll(Collection<? extends Object> stuff) {,则编译将确定输入参数的最常见类型"为Collection<Object>.现在,我用下面的代码重写了通用方法,但是在重写方法-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

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

    }
}

我想知道的是,在类型擦除之后,这些方法的外观如何,我认为它们的外观类似于public void saveAll(Collection 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.

请注意,我知道使用"javap"编译后可以看到字节码,但是它并没有告诉我这些方法在类型擦除"之后会是什么样子.

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


更新:
这个问题没有回答我的问题,如果在类型擦除之后两个方法都变为public void saveAll(Collection stuff) {,那么为什么子类会出现覆盖错误,因为使用public void saveAll(Collection<Object> stuff) {子类会通过覆盖规则.


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.

一秒钟拿走仿制药.

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) {
  }
}

在此,saveAll重载而不是覆盖父级的saveAll.

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

用异物代替T?并没有真正改变这一点-编译器正在尝试创建一个重载父方法的方法,但随后意识到它不能在编译时类型上分派.

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.

[编辑,请参见Lew Block对原始内容的评论:类型擦除之前,编译器需要确定子方法是覆盖还是重载了父方法"

[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]

这篇关于类型擦除和覆盖通用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 05:55