[英]Lower bounded wildcard (Comparable<? super K>)
在集合中,經常使用Comparable
接口,例如。 在PriorityQueue
:
private static <T> void siftUpComparable(int k, T x, Object[] es) {
Comparable<? super T> key = (Comparable<? super T>) x;
...
if (key.compareTo((T) e) >= 0)
break;
...
}
比如說,我們創建整數隊列並添加一些內容:
PriorityQueue<Integer> queue = new PriorityQueue<>();
queue.add(1);
如果我得到通配符的概念,使用<? super T>
的唯一效果 <? super T>
而不是<T>
是編譯器擴展compareTo
的可能參數類型
public interface Comparable<T> {
public int compareTo(T o);
}
到任何超類Integer
。 但我想知道為什么以及如何在這里使用它。 任何一個例子
Comparable<T> key = (Comparable<T>) x;
是不足夠的? 或者它是使用“超級”通配符與可比較的指南?
放寬通用簽名可以提高代碼的靈活性,尤其是在我們討論參數類型時。 一般准則是PECS規則,但是對於Comparable
,需要這種靈活性的實際例子很少見,因為它們意味着具有在其所有子類型中定義自然順序的基本類型。
例如,如果您有類似的方法
public static <T extends Comparable<T>> void sort(Collection<T> c) {
}
你不能做以下
List<LocalDate> list = new ArrayList<>();
sort(list); // does not compile
原因是LocalDate
實現了ChronoLocalDate
,您可以將ChronoLocalDate
所有實現相互比較,換句話說,它們都實現了Comparable<ChronoLocalDate>
。
因此,方法簽名必須是
public static <T extends Comparable<? super T>> void sort(Collection<T> c) {
}
允許實際類型實現Comparable
參數Comparable
超類型,就像已聲明Collections.sort
一樣。
對於siftUpComparable
的特定情況,即沒有機會確定實際通用簽名的內部Collection方法,它是否使用Comparable<T>
或Comparable<? super T>
無關緊要Comparable<? super T>
Comparable<? super T>
,正如它所需要的,是將T
的實例傳遞給compare
方法的能力,而即使提供實際的參數也是由另一個未經檢查的強制轉換完成的。
實際上,由於未選中類型轉換,它也可以是Comparable<Object>
,這將消除在compare
調用時compare
(T)
的需要。
但顯然,作者並不打算離開實際通用代碼所做的太遠而使用相同的模式,即使它在這里沒有明顯的好處。
E
可能實際上沒有為自己的類暴露出類似的東西。 想象一下這個案例:
class Foo implements Comparable<Foo> { ... }
class Bar extends Foo { ... }
如果您創建PriorityQueue<Bar>
的優先級隊列,則使用Foo
定義的比較方法。 即,你有一個Comparable<? super Bar>
Comparable<? super Bar>
其中通配符被實現為Foo
仿制葯的重點是類型安全。 由於Java泛型在運行時丟失了類型信息,因此我們沒有驗證此強制轉換的方法。 有界通配符是一種在編譯時驗證類型限制的安全方法,而不是在運行時制作一個hail Mary。
要理解super
的不同語義並在泛型中extends
,請參考以下主題:
什么是PECS(制作人擴展消費者超級)?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.