簡體   English   中英

下限通配符(Comparable <?super K>)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM