2016-03-01 134 views

回答

19

您提出的簽名可能適用於Java-8。然而在以前的Java版本中,類型推斷並不那麼聰明。考慮你有List<java.sql.Date>。請注意,java.sql.Date延伸java.util.Date其實施Comparable<java.util.Date>。當你編譯時

List<java.sql.Date> list = new ArrayList<>(); 
Collections.sort(list); 

它在Java-7中完美的工作。這裏推薦Tjava.sql.Date,實際上是Comparable<java.util.Date>,即Comparable<? super java.sql.Date>。但是讓我們試試你的簽名:

public static <T extends Comparable<T>> void sort(List<? extends T> list) {} 

List<java.sql.Date> list = new ArrayList<>(); 
sort(list); 

這裏T應該被推斷爲java.util.Date。但是Java 7規範不允許這樣的推斷。因此,該代碼可與Java-8進行編譯,但失敗時的Java-7下彙編:

Main.java:14: error: method sort in class Main cannot be applied to given types; 
     sort(list); 
     ^
    required: List<? extends T> 
    found: List<Date> 
    reason: inferred type does not conform to declared bound(s) 
    inferred: Date 
    bound(s): Comparable<Date> 
    where T is a type-variable: 
    T extends Comparable<T> declared in method <T>sort(List<? extends T>) 
1 error 

類型推斷用Java-8大大提高。單獨的JLS chapter 18現在專用於此,而在Java-7中,規則were要簡單得多。

+1

但是,static > T max(Collection c)工作正常......這又是一個推理問題嗎? – prvn

+0

@prvn,在這裏你有'Comparable '而不是'Comparable '就像你的簽名中一樣。 ''T擴展Comparable >無效排序(列表列表)'也會工作,但添加'?擴展T'在這裏完全沒有必要,而在'max'方法中合理(如'max'返回值)。 –

+6

還有一點。當你有一個像'List list'這樣的通配符類型時,由於通配符類型的工作方式,你不能在該方法內執行'list.set(index,list.get(anotherIndex))'。這可以通過內部幫助方法來避開'?將T'擴展到另一個類型變量(或者通過使用未經檢查的操作,正如內部實現經常這樣做),但是仍然沒有通配符的類型對於將要修改的列表來說更清晰。 – Holger

4

它們不同,因爲? super TT的限制性更小。這是一個Lower Bounded Wildcard(鏈接的Java教程說,在部分)

術語List<Integer>List<? super Integer>更嚴格,因爲前者只匹配Integer類型的列表,而後者匹配任何類型的列表超類型Integer

替換IntegerT和它意味着T一個java.lang.Object

+0

但我越來越靈活的sort()..參數的使用? – prvn

+0

是的,沒有人說'List <?超級整數>'與列表'相同。第二個版本使用'extends',問題是如果這樣做是平等的。 – JojOatXGME

+0

我不認爲你的回答與問題直接相關。 – yuxh

9
// 0 
public static <T extends Comparable<? super T>> void sort0(List<T> list) 

// 1 
public static <T extends Comparable<T>> void sort1(List<? extends T> list) 

這些簽名不同,因爲它們在T類型和在T定義的類型參數Comparable之間的關係提出不同的要求。

假設,例如,你有這個類:

class A implements Comparable<Object> { ... } 

然後,如果你有

List<A> list = ... ; 
sort0(list); // works 
sort1(list); // fails 

原因sort1失敗是有沒有類型T既媲美本身也就是說,或者是列表類型的超類型。

事實證明,類A的格式不正確,因爲Comparable的對象需要滿足某些要求。特別是反轉比較應該會改變結果的符號。我們可以將A的實例與Object進行比較,但反之亦然,因此違反了此​​要求。但請注意,這是語義Comparable的要求,並不是由類型系統強加的。僅考慮類型系統,兩個sort聲明確實不同。

相關問題