2016-09-20 78 views
4

为什么不下面的代码生成编译时未检查警告:为什么这个协变返回类型声明不会产生unckecked警告?

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

寻找[Java Unchecked Overriding Return Type](http://stackoverflow.com/questions/23645753/java-unchecked-overriding-return-type)。 – DimaSan

+0

@DimaSan它实际上并不能解释为什么我的第一个示例在稍后的时候不会生成编译警告。 –

回答

4

因为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. Subtyping among Class and Interface Types

给出一个通用的类型声明C<F1,...,Fn>(N> 0)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对 的 StringSorter定义时给予未经检查的警告,因为 Overrider.toList返回类型是List,这是不返回类型的 重写的方法的一个亚型,List<String>(撞击矿)

JLS例子8.4.8.3-1 & 8.4.8.3-2和具体:

8.4.8.3. Requirements in Overriding and Hiding

如果一个方法声明D1与返回类型R1覆盖或隐藏 声明另一种方法D2与返回类型R2,然后D1必须为D2,或编译时错误发生 是 返回型取代(§8.4.5)。

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

如果R1不是R2的一个子类型,除非SuppressWarnings注释抑制编译时未检查的警告发生 (§9.6.4.5)。

+0

'List '是原始'List'的子类型吗? –

+0

@JaimeHablutzel,“原始类型是没有任何类型参数的泛型类或接口的名称。”所以,一个'List '是一个定义了类型参数的列表。 – ChiefTwoPencils

+0

从JLS中,'如果R1不是R2的**子类型**,除非受到SuppressWarnings注释(§9.6.4.5).'和您的语句',这代表您的第一个示例在那里,孩子的返回类型是父类型的一个子类型',这就可以解释为什么警告不是在我的第一个例子中发出的,但是我在JLS中找不到它,它说“列表'实际上是'List'的**子类型**,请澄清。 –

相关问题