簡體   English   中英

Java泛型-為什么不允許我做可比 <? extends T> 而不是可比 <? super T> ?

[英]Generics in Java - Why I am not allowed to do Comparable<? extends T> instead of Comparable<? super T>?

我已經根據Jon Skeet的答案重寫了這個ArrayIndexComparator類,以便它可以支持通用類型: 排序后獲取數組的索引?

public class ArrayIndexComparator<T extends Comparable<? super T>> implements Comparator<Integer> {
    private final T[] array;

    public ArrayIndexComparator(T[] array) {
        this.array = array;
    }

    public Integer[] createIndexArray() {
        Integer[] indexes = new Integer[array.length];
        for (int i = 0; i < array.length; i++) {
            indexes[i] = i; // Autoboxing
        }
        return indexes;
    }

    @Override
    public int compare(Integer index1, Integer index2) {
        // Autounbox from Integer to int to use as array indexes
        return array[index2].compareTo(array[index1]);
    }
}

我還可以只要使用這個類T類型或的超類型T實現Comparable接口( Comparable<? super T>

如果我寫Comparable<? extends T> Comparable<? extends T>而不是Comparable<? super T> Comparable<? super T> ,編譯器給我一個錯誤:

@Override
public int compare(Integer index1, Integer index2) {
    // Autounbox from Integer to int to use as array indexes
    return array[index2].compareTo(array[index1]); // ERROR -> compareTo (capture<? extends T>) in Comparable cannot be applied to (T)
}

compareTo (capture<? extends T>) in Comparable cannot be applied to (T)錯誤是什么意思?

我認為它沒有意義定義一個類AClass它實現Comparable<AChildClassOfAClass>但仍是可能的:

class AClass implements Comparable<AChildClassOfAClass> {


    @Override
    public int compareTo(AChildClassOfAClass o) {
        return 0;
    }
}

class AChildClassOfAClass extends AClass {
}

在這種奇怪的情況下,如果我已將其定義為ArrayIndexComparator<T extends Comparable<? extends T>>則假定能夠使用ArrayIndexComparator ArrayIndexComparator<T extends Comparable<? extends T>> ArrayIndexComparator<T extends Comparable<? extends T>> ,因為在這種情況下TAClass它實現Comparable<AChildClassOfAClass>這原來是的一個子類AClass (因此Comparable<? extends T>Comparable<AChildClassOfAClass extends AClass>

當然,使用Comparable<? super T>更有意義Comparable<? super T> Comparable<? super T> ,但是我想我應該可以這樣做。

為什么Java不允許我這樣做?

非常感謝您的關注。

編輯:閱讀問題的答案后< 超級T>和<? 在Java中擴展了T> ,這是我的理解,希望我能正確理解:

array[index1]的類型為T,但是compareTo期望的類型為<? extends T> <? extends T>即,一個未知的特定類型的T (或T本身,但是編譯器不能保證)。

因此,編譯器無法安全地將T轉換為特定的未知類型,而如果我們使用<? super T> <? super T>因為在這種情況下compareTo將期望T的未知超類型作為參數,並且當我們傳遞T ,編譯器可以安全地將類型T強制轉換為其超類型,因為類型T也是Tsupertype of T (例如我們說Integer也是Number ,但Number不一定是Integer )。

在此Comparable<? extends T> Comparable<? extends T>情況下,我們試圖通過將array[index1]傳遞給compareTo方法來使用它,但是編譯器無法安全地將類型T compareTo(<? extends T>)所需的特定類型。

這就是為什么我得到錯誤。

這是對的想法嗎?

這種錯誤通常意味着您正在嘗試對沒有意義的約束進行編碼。 在您的情況下,我們已經知道有些不合理的事情:

在這種情況下TAClass它實現Comparable<AChildClassOfAClass>

是真正的問題。 您的類允許您執行base.compareTo(child) ,但不能執行child.compareTo(base) 您已經調整了通用參數來處理此問題,但您只是將問題推到了其他地方(幸運的是,編譯器足夠聰明地發現了它!)。

錯誤實際上是在說什么

compareTo需要一個? extends T ? extends T 即擴展T某些特定但未知的類型。 編譯器抱怨是因為我們試圖傳遞T通常與未知類型相同(也不能分配給該未知類型)。 我們唯一可以傳遞給這種方法的是null

進一步閱讀

要管理一個? 泛型類型參數,編譯器使用“捕獲”; 在你的情況下, capture-of-? super T capture-of-? super T

通用術語? super T ? super T表示“ ? super T任何超類”; 所以注意它可以是Object ; 因此,在調用該方法時,您可能會有一個Comparable<Object> 但是,這是無效的:

Comparable<AChildClassOfAClass> yourComparable == new YourClass();
yourComparable.compareTo(new Object());

這就是您的代碼在該定義中可能涉及的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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