两种方法都有相同的删除

时间:2017-07-03 09:32:54

标签: java generics override

我已经阅读了类似的问题,并且知道通用删除会在同一类中导致此错误。但我无法理解为什么以下代码不起作用。

我设计了一些例子。并发现许多令人困惑的事情。

public static class Father<S> {

    public void foo(Set<String> s) {...}

    public void bar(S s) {...}

    public void baz(String s) {...}
}


public static class Son<E> extends Father {

    public void foo(Set<String> s) {...} **// error**

    public void bar(E e) {...} **// error**
 // public void bar(Object e) {...} // This works

    public void baz(String s) {...}
}


public static class Daughter<E> extends Father<T> {

    public void foo(Set<String> s) {...} **// error**

    public void bar(Object e) {...}

    public void baz(String s) {...} **// error**
}

如你所见,我有几个错误。这是我的问题:

  1. 让我们关注FatherSon。为什么baz有效,而foo没有?
  2. 让我们在bar中看到Son。为什么Object e有效,而E e失败?我认为E将被删除为Object
  3. 让我们看看Daughter,为什么baz失败,与Son相比?
  4. 请有人告诉我为什么会这样吗?非常感谢! (我知道我不应该使用原始类。但为什么这会导致错误?)

2 个答案:

答案 0 :(得分:1)

问题在于Son<E>扩展了原始Father类。

因此foo类的barSon不会覆盖

public void foo(Set<String> s) {}

public void bar(S s) {}
Father类的

,(擦除后)成为

public void foo(Set s) {}

public void bar(Object s) {}

并在Son类中删除相同名称的方法。

Son的声明更改为

public static class Son<E> extends Father<E>

将解决错误。

baz方法没有问题,因为它没有泛型参数,因此子类的baz会覆盖基类的baz

Daughter课程中,不清楚T的来源。如果您将T更改为E,则所有错误都会消失。

哦,void bar(Object e)适用于原始示例,因为它覆盖void bar(S s)的{​​{1}}(由于Father扩展了原始Son这一事实

答案 1 :(得分:1)

这里:

public class Son<E> extends Father {

您在扩展类的定义中使用原始Father 这是一种不好的做法 你应该写:

public class Son<E> extends Father<E> {

使用原始类型在继承方面也会产生影响 来自JLS

  

原始类型的超类(分别是超级接口)是   删除任何一个的超类(超级接口)   泛型类型的参数化。

和:

  

类的超类型可以是原始类型。会员访问   class被视为正常,超类型的成员访问是   处理原始类型。

因此,Son不考虑父类中的泛型 对于Son,这个继承的方法:

public void foo(Set<String> s) {
}
确实绑定为:

public void foo(Set s) {
}

因此,子方法和父方法具有相同的擦除,但子方法不会覆盖父方法,因为您不使用完全相同的类型:

public void foo(Set<String> s) {...} **// error**

如果您以这种方式覆盖以符合Father的原始版本:

public void foo(Set s) {...} 

它会编译。

对于带有泛型的bar()方法,它是完全相同的。

这:

public void bar(E e) 

将被绑定为:

public void bar(Object e) 

你得到同样的问题......

我不会解释所有要点,因为我不认为它有用 你得到的是不良做法的结果。

士气是你不得使用原始类型设计用于泛型,因为它可能会对他们的初始意图和类的使用产生严重的副作用。

这个

public static class Son<E> extends Father {

应该是:

public static class Son<E> extends Father<E>  {

而且:

public static class Daughter<E> extends Father<T> {

应该是:

public static class Daughter<E> extends Father<E> {