2008-10-30 68 views
7

我注意到了Collections.sort的specificaition:爲什麼SomeClass <? super T>不等於Java泛型中的SomeClass <T>?

public static <T> void sort(List<T> list, Comparator<? super T> c) 

爲什麼 「? super」 必要嗎?如果ClassB擴展爲ClassA,那麼我們不能保證Comparator<ClassA>能夠比較兩個ClassB對象,沒有「? super」部分?

換句話說,鑑於此代碼:

List<ClassB> list = . . . ; 
Comparator<ClassA> comp = . . . ; 
Collections.sort(list, comp); 

爲什麼不是編譯器足夠聰明,知道這是OK,即使沒有指定「? super」爲Collections.sort的聲明()?

回答

7

Josh Bloch今年在Google I/O上進行了一次演講,名爲Effective Java Reloaded,您可能會感興趣。它講述了一個名爲「Pecs」的助記符(生產商extends,消費者super),這就解釋了爲什麼在輸入參數中使用? extends T? super T(僅限於;從不使用返回類型)以及何時使用哪個。

+0

謝謝,這是一個有用的演示文稿。我認爲我的問題的根源是第一張真正的幻燈片:列表不是列表的子類,其方式是String []是Object []的子類。 – Kip 2008-10-30 19:42:43

0

很明顯,在Comparator的情況下,任何一個T的祖先都可以工作。但是編譯器並不知道類Comparator這樣的功能 - 只需要知道它應該允許<T>還是<? super T>

從另一種角度看,是的,任何一個祖先的Comparator都可以在這種情況下工作 - 而圖書館開發人員說的方式是使用<? super T>

+0

但它不僅對我很明顯 - 比較器意味着它有一些函數只能用於T類型的對象。因爲ClassB的所有對象都是ClassA的對象,所以比較器的所有功能都只適用於ClassA也在ClassB上工作。 AFAIK – Kip 2008-10-30 19:13:40

1

這與C#類似,前兩天我剛剛瞭解到它的原因(困難的方法,然後是PDC的信息方式)。

假設Dog extends Animal

Blah<Dog>一樣Blah<Animal>他們即使Dog延伸Animal完全不同類型的簽名。

例如,假設上Blah<T>的方法:

T Clone(); 

Blah<Dog>這是Dog Clone();而在Blah<Animal>這是Animal Clone();

您需要一種方法來區分編譯器可以說Blah<Dog>Blah<Animal>相同的公共接口,這就是<? super T>指示 - 使用爲T任何類都可以在Blah<? super T>方面減少到其超類。

(在C#4.0中,這將是Blah<out T>我相信。)

0

對你的問題的簡單回答是,圖書館設計者想給圖書館用戶提供最大的靈活性;例如這種方法簽名可以讓你做這樣的事情:

List<Integer> ints = Arrays.asList(1,2,3); 
Comparator<Number> numberComparator = ...; 

Collections.sort(ints, numberComparator); 

使用通配符防止您被強制使用Comparator<Integer>;圖書館設計者指定該語言需要通配符的事實使他或她能夠允許或限制這種使用。

相關問題