2016-05-06 72 views
6

我有以下看似類似的方法,do1do2爲什麼Java的推理失敗

class Demo<A>{ 
    public <C> Iterable<C> do1(List<? super C> _a) { 
     return null; 
    } 


    public <C extends D, D> Iterable<C> do2(List<D> _a) { 
     return null; 
    } 

    { 
     List<? extends A> leA = null; 

     do2(leA); 
     do1(leA); 
    } 
} 

當我編譯上面的代碼(javac的1.8.0_92),調用do2(leA)作品而do1(leA)失敗。

required: List<? super C> 
found: List<CAP#1> 
reason: cannot infer type-variable(s) C 
(argument mismatch; List<CAP#1> cannot be converted to List<? super C>) 
where C,A are type-variables: 
    C extends Object declared in method <C>do1(List<? super C>) 
    A extends Object declared in class Cache 
where CAP#1 is a fresh type-variable: 
    CAP#1 extends A from capture of ? extends A 

現在我想知道:這是由於不完整的javac實現類型推斷的,還是我創建一個無效的類型樹的do1(leA)調用?

因爲據我所知:

  • do1(leA)Capture(? extends A)成爲ç
  • 的超類型在do2(leA)Capture(? extends A)變成C的超類型(間接通過:Capture(? extends A) == DD :> C

意義在這兩種情況下C應該(沒有錯誤)解析爲"? extends A"

+4

我可以用JDK 1.8.0_51重現這一點。僅供參考,Eclipse Mars.2編譯好了...... – Tunaki

+1

使用'1.8.0_91-b14'也可以編譯我。 IIRC,更新40是越野車 - 這可能是一個錯誤。也許只是更新你的Java版本。 – Bohemian

+1

感謝您的支持,我更新到1.8.0_92,仍然得到相同的編譯錯誤:http://pastebin.com/tEUfX2JC –

回答

-2

你需要extends Csuper C

public <C> Iterable<C> do1(List<? extends C> _a) { 

Csuper是和祖先,而不是一個子類。

+0

我也探討過這個選項,它將編譯(這將使do1中的類型樹不同於do2)。但我感興趣的是爲什麼方法看似相似的類型樹不能成功編譯.. –