2016-09-20 128 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'的**子類型**,請澄清。 –

相關問題