[英]Java generics: How to cast to (T extends Comparable<? super T>) without raw-types
[英]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>>
,因為在這種情況下T
是AClass
它實現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
也是T
的supertype of T
(例如我們說Integer
也是Number
,但Number
不一定是Integer
)。
在此Comparable<? extends T>
Comparable<? extends T>
情況下,我們試圖通過將array[index1]
傳遞給compareTo
方法來使用它,但是編譯器無法安全地將類型T
compareTo(<? extends T>)
所需的特定類型。
這就是為什么我得到錯誤。
這是對的想法嗎?
這種錯誤通常意味着您正在嘗試對沒有意義的約束進行編碼。 在您的情況下,我們已經知道有些不合理的事情:
在這種情況下
T
是AClass
它實現Comparable<AChildClassOfAClass>
這是真正的問題。 您的類允許您執行base.compareTo(child)
,但不能執行child.compareTo(base)
。 您已經調整了通用參數來處理此問題,但您只是將問題推到了其他地方(幸運的是,編譯器足夠聰明地發現了它!)。
compareTo
需要一個? extends T
? extends T
即擴展T
某些特定但未知的類型。 編譯器抱怨是因為我們試圖傳遞T
通常與未知類型相同(也不能分配給該未知類型)。 我們唯一可以傳遞給這種方法的是null
。
為什么泛型類型不適用於自變量擴展兩者的超類? (相同問題的簡單變體)
什么是PECS? (一種思考super
與extends
通配符的結構化方法)
要管理一個?
泛型類型參數,編譯器使用“捕獲”; 在你的情況下, 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.