2012-06-11 85 views
3

我有一個類,它有一個自引用泛型參數和一個超類相同的參數。靜態函數與類具有相同的邊界。Java嵌套自引用泛型

public class Bar<T extends Bar<T, C>, C extends Bar<C, ?>> { 

    Bar() { 
     foo((T) null); 
     foo((C) null);//compile error 
    } 

    static <S_T extends Bar<S_T, S_C>, S_C extends Bar<S_C, ?>> void foo(S_T t) { 
    } 
} 

這給出了以下錯誤。

界不匹配:式酒吧< T,C>的一般方法foo(S_T)不 適用於參數(C)。推斷C型不是有效 替代有界參數< S_T延伸酒吧< S_T,S_C >>

我想不通爲什麼C不能在自CBar<C,?>傳遞給foo()並且通配符是Bar,因爲聲明中的第二個參數表示它擴展了Bar。

我知道這可能是一個壞主意,併產生很難理解的代碼,但我真的想知道爲什麼這不編譯。

+0

可能與我的問題http://stackoverflow.com/questions/9937422/a-bad-interaction-between-self-referential-types-:換句話說,編譯錯誤即使有這樣的代碼仍然存在and-bound-wildcards –

+0

@JudgeMental有點類似;但從我從你的問題中收集到的是類層次結構無法編譯,而我的類層次結構編譯但失敗了函數的參數約束。 – dege

回答

0

我不是泛型一條縫,但我認爲問題是,你聲明的foo()的類型是

<S_T extends Bar<S_T,S_C> > void foo(S_T) 

,然後調用它需要不同的靜態兩種不同的上下文鍵入foo()

在第一種情況下,S_T的類型爲T,在第二種情況下,它的類型爲C。但是TC被聲明爲Bar<T,?>Bar<C,?>,它們是靜態不兼容的類型。 我猜想編譯器會在第一次調用時計算出foo()的類型,然後假定正確,類型必須始終保持不變,而不是。

+0

切換兩個foo()調用的順序仍然給出與C一致的錯誤。 – dege

+0

OK,嘗試更改類聲明中C和T的順序,即。do Bar ,T延伸Bar 。如果錯誤翻轉,那麼這意味着類型綁定也取決於類聲明中類型的順序。但是在任何一種情況下,C和T都有不同的不兼容類型,你不能將它們都傳遞給foo()。 – Jochen

+0

我試着改變你的建議,並將錯誤更改爲T,但我認爲這只是因爲它所做的只是重命名參數,而沒有改變任何意義。我嘗試了幾種不同的方法來記錄參數,並將錯誤留在具有通配符的參數上。 另外我認爲,雖然C和T與eachother不兼容,但兩者都應該與靜態函數兼容,因爲AFAIK的泛型參數是基於它獲得每次調用的輸入。 – dege

2

簡短的回答是,Java類型推斷實際上是非常蹩腳的。

爪哇不在的Bar聲明上通配符?執行任何智能推理來推斷出,它在邏輯上由Bar< ?, ? >界(非彼?在那隻結合本身被界定,等等)。一旦你自己把?,這是所有的Java知道。儘管沒有什麼能阻止你在Bar的聲明中將通配符放在通配符中,但即使這樣也不能幫助Java; Java永遠不會假定兩個單獨的?指的是同一類型,即使更深入的分析意味着它們必須是。

public class Bar<T extends Bar<T, C>, C extends Bar<C, ? extends Bar<?, ? extends Bar<?, ?>>>> { 

    Bar() { 
     foo((T) null); 
     foo((C) null);//compile error 
    } 

    static <S_T extends Bar<S_T, S_C>, S_C extends Bar<S_C, ? extends Bar<?, ? extends Bar<?, ?>>>> void foo(S_T t) { 
    } 
} 
+0

是的,我開始懷疑java無法檢測通配符邊界之間的連接。 我開始嘗試提供一個類:'Pie extends Bar '而不是通配符。然後函數會有',S_C擴展吧'和一個仍然可以在Bar上返回S_C的方法....但是我現在可能完全脫離目標(這裏幾乎凌晨3點) – dege

+0

什麼是「#< S_T, S_C >'作爲」foo「的參數類型錯誤?無論如何,你可以在'foo'中使用關於'S_T'的唯一信息就是它是'Bar < S_T, S_C >'。此外,使'foo'(理論上至少)更一般。 –

+0

該函數的通用參數是什麼?你的意思是隻是定義S_T和S_C沒有任何界限,因爲然後參數中的將與Bar類的界限不匹配 – dege