因为List
不是 的子类型,List<String>
但(如您所知)List<String>
是的子类型List
。
JLS 中给出的示例:
class C implements Cloneable {
C copy() throws CloneNotSupportedException {
return (C)clone();
}
}
class D extends C implements Cloneable {
D copy() throws CloneNotSupportedException {
return (D)clone();
}
}
这代表您的第一个示例,其中子级的返回类型是父级的子类型。同样,在您的示例中,List<String>
是List
.
4.10.2. 类和接口类型之间的子类型化
给定一个泛型类型声明C<F1,...,Fn>
(n > 0),泛型类型的直接超类型C<F1,...,Fn>
如下:
- 的直接超类
C<F1,...,Fn>
。
- 的直接超接口
C<F1,...,Fn>
。
- type
Object
, ifC<F1,...,Fn>
是没有直接超接口的通用接口类型。
- 原始类型
C
。 (我的勇气)
尽管:
class StringSorter {
// turns a collection of strings into a sorted list
List<String> toList(Collection<String> c) {...}
}
class Overrider extends StringSorter {
List toList(Collection c) {...}
}
是您的第二个片段的示例。
Overrider
在针对 的新定义进行编译时,将给出未经检查的警告,StringSorter
因为
Overrider.toList
isList
的返回类型不是被覆盖方法的返回类型的子类型,List<String>
。(打击我的)
JLS示例8.4.8.3-1和8.4.8.3-2,特别是:
8.4.8.3。覆盖和隐藏的要求
如果具有返回类型R1的方法声明d1覆盖或隐藏具有返回类型R2的另一个方法d2的声明,则d1必须是 d2 的返回类型可替换(第 8.4.5 节),否则会发生编译时错误。
此规则允许协变返回类型 - 在重写方法时改进方法的返回类型。
如果R1不是R2的子类型,则会出现编译时未经检查的警告,除非被SuppressWarnings
注释抑制(第 9.6.4.5 节)。