4

为什么以下代码不会产生编译时未经检查的警告:

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 中寻找这种行为的参考。

4

1 回答 1

5

因为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.toListisList的返回类型不是被覆盖方法的返回类型的子类型,List<String>(打击我的)

JLS示例8.4.8.3-18.4.8.3-2,特别是:

8.4.8.3。覆盖和隐藏的要求

如果具有返回类型R1的方法声明d1覆盖或隐藏具有返回类型R2的另一个方法d2的声明,则d1必须是 d2 的返回类型可替换(第 8.4.5 节)否则会发生编译时错误。

此规则允许协变返回类型 - 在重写方法时改进方法的返回类型。

如果R1不是R2的子类型,则会出现编译时未经检查的警告,除非被SuppressWarnings注释抑制(第 9.6.4.5 节)。

于 2016-09-20T22:43:49.097 回答