为什么以下代码不会产生编译时未经检查的警告:
class Parent {
public List method(){
return null;
}
}
class Child extends Parent {
public List<String> method() {
return null;
}
}
而以下实际上是:
class Parent {
public List<String> method(){
return null;
}
}
class Child extends Parent {
public List method() {
return null;
}
}
我实际上是在JLS中寻找这种行为的参考。
答案 0 :(得分:4)
由于List
不是List<String>
的子类型,但(如您所知)List<String>
是<{1}}的子类型。
JLS中给出的示例:
List
这表示您的第一个示例,其中子项中的返回类型是父项的子类型。同样,在您的示例中,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>
的子类型。
4.10.2. Subtyping among Class and Interface Types
给定泛型类型声明
List
(n> 0),通用的直接超类型 类型C<F1,...,Fn>
是以下所有内容:
- 的直接超类
C<F1,...,Fn>
。- 的直接超接口
C<F1,...,Fn>
。- 类型
C<F1,...,Fn>
,如果Object
是没有直接超接口的通用接口类型。- 原始类型
C<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
的new定义因为返回类型StringSorter
是Overrider.toList
,它不是返回类型的子类型 重写方法List
。 (打击我的)
JLS示例8.4.8.3-1&amp; 8.4.8.3-2,具体而言:
8.4.8.3. Requirements in Overriding and Hiding
如果返回类型 R1 的方法声明 d1 覆盖或隐藏 声明另一个方法 d2 ,返回类型 R2 ,那么 d1 必须是 d2 的return-type-substitutable(第8.4.5节),或编译时错误 发生。
此规则允许协变返回类型 - 改进返回类型 覆盖它时的方法。
如果 R1 不是 R2 的子类型,则会发生编译时未经检查的警告 除非被
List<String>
注释(第9.6.4.5节)抑制。