为什么这个协变返回类型声明不会产生无法解释的警告?

时间:2016-09-20 22:27:16

标签: java jls covariant-return-types

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

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

1 个答案:

答案 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 定义因为返回类型   StringSorterOverrider.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节)抑制。