我已经阅读了类似的问题,并且知道通用删除会在同一类中导致此错误。但我无法理解为什么以下代码不起作用。
我设计了一些例子。并发现许多令人困惑的事情。
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**
}
如你所见,我有几个错误。这是我的问题:
Father
和Son
。为什么baz
有效,而foo
没有?bar
中看到Son
。为什么Object e
有效,而E e
失败?我认为E
将被删除为Object
?Daughter
,为什么baz
失败,与Son
相比?请有人告诉我为什么会这样吗?非常感谢! (我知道我不应该使用原始类。但为什么这会导致错误?)
答案 0 :(得分:1)
问题在于Son<E>
扩展了原始Father
类。
因此foo
类的bar
和Son
不会覆盖
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> {