2010-01-28 31 views
4

[更新]真實情況比我看起來最初的問題稍微複雜一些。 [/ UPDATE]當類型爲通配符時如何將泛型結果用作泛型參數?

我有點被以下行爲難住了。鑑於這樣的代碼:

interface Inter<T> { 
    T makeT(); 
    void useT(T t); 
} 

public class Foo { 
    public void bar(Qux q) { 
    Inter<?> x = getInterForQux(q); 
    x.useT(x.makeT()); 
    } 

    Inter<?> getInterForQux(Qux q) { 
    if(someTest(q)) { 
     return (Inter<Integer>) mkAnInterInt(); 
    } else { 
     return (Inter<Double>) mkAnInterDouble(); 
    } 
    } 
} 

javac的給我的錯誤:

useT(capture#478 of ?) in Inter<capture#478 of ?> cannot be applied to (java.lang.Object)

而Eclipse的給我:

The method useT(capture#1-of ?) in the type Inter<capture#1-of ?> is not applicable for the arguments (capture#2-of ?)

顯然,不管是什麼TmakeT()結果類型是與參數類型useT()相同。爲什麼我不能這樣做?有沒有解決方法?

回答

4

當您使用通配符時,編譯器無法看到返回類型x.makeT()和參數類型x.useT()是相同的。爲了保證他們都是一樣的,你應該使用這裏的泛型方法:

public class Foo { 
    public <T> void bar(Inter<T> x) { 
     x.useT(x.makeT()); 
    } 
} 
+0

實際情況並非如此瑣碎這給你bar相同的簽名,如上所述。首先,'bar'實際上是一種接口方法,所以我不能只在其上粘貼類型量詞。但我認爲你總是可以重構代碼,通過將T的「範圍」推入私有方法爲量詞騰出空間。 – 2010-01-28 22:33:37

1

這是合乎邏輯的,因爲Inter<?>.makeT()可以返回任何東西,Inter<?>.useT(..)消耗任何東西,但兩個anythings可以是不同的。

這將解決這個問題:

public <T> void bar(Inter<T> x) { 
    x.useT(x.makeT()); 
} 
+0

這完全不合邏輯:''x''只能有一個類型和一個類型變量。但你的建議是正確的。 – 2010-01-28 22:34:49

+0

它是 - 通用類型在運行時被擦除。 – Bozho 2010-01-28 22:44:22

+0

是的,顯然編譯器不能利用運行時不可用的任何東西。 – 2010-01-28 22:49:43

0

使用捕捉助手:

public void bar(Qux q) { 
    Inter<?> x = getInterForQux(q); 
    barPrivate(x); 
} 
private <T> void barPrivate(Inter<T> x) { 
    x.useT(x.makeT()); 
} 

,只要你想