我根据Jon Skeet的回答重写了这个ArrayIndexComparator
类,以便它可以支持泛型类型:Get the indices of an array after sorting?
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<? 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
,我假设能够使用ArrayIndexComparator<T extends Comparable<? extends T>>
,因为在这种情况下T
是AClass
,它实现{ {1}}结果是Comparable<AChildClassOfAClass>
的子类(因此AClass
→Comparable<? extends T>
)。
当然,使用Comparable<AChildClassOfAClass extends AClass>
更有意义,但我想如果我愿意,我应该能够做到。
为什么Java不允许我这样做?
非常感谢你的关注。
编辑:在阅读问题Difference between <? super T> and <? extends T> in Java的答案后,这是我理解的内容,我希望我理解正确:
Comparable<? super T>
属于T类型,但array[index1]
期望类型compareTo
,即未知的特定类型的<? extends T>
(或T
本身,但是编译器无法保证)。
因此,编译器无法安全地将T
转换为特定的未知类型,而如果我们使用T
则可以执行此操作,因为在这种情况下<? super T>
会预期未知作为参数的compareTo
的超类型,并且当我们传递T
时,编译器可以安全地将类型T
强制转换为其超类型,因为类型T
也是T
1}}(就像我们说supertype of T
也是Integer
,但Number
不一定是Number
。
在这个Integer
的情况下,我们尝试将Comparable<? extends T>
传递给array[index1]
方法,但编译器无法安全地转换类型compareTo
到T
所需的特定类型,这是未知的。
这就是我收到错误的原因。
这个想法是对的吗?
答案 0 :(得分:1)
这种错误通常意味着您正在尝试编码一个没有意义的约束。在你的情况下,我们已经知道有些事情没有意义:
在这种情况下
T
是AClass
,它实现了Comparable<AChildClassOfAClass>
这个是真正的问题。您的课程允许您base.compareTo(child)
,但不能child.compareTo(base)
。你已经调整了通用参数来处理这个问题,但是你只是把问题推到别处(幸运的是编译器很聪明地发现它!)。
compareTo
需要? extends T
。即一些扩展T
的特定但未知的类型。编译器抱怨是因为我们试图传入T
- 一般而言,它与未知类型不同(也不可分配)。我们唯一可以传递给这种方法的是null
。
Why generic type is not applicable for argument extends super class for both?(考虑super
与extends
通配符的结构化方式)
答案 1 :(得分:-1)
要管理?
泛型类型参数,编译器使用&#34; capture&#34 ;;在您的情况下,capture-of-? super T
。
通用术语? super T
表示&#34; T&#34;的任何超类;所以请注意它可以是Object
;因此调用该方法时可能会有Comparable<Object>
。但是,这是无效的:
Comparable<AChildClassOfAClass> yourComparable == new YourClass();
yourComparable.compareTo(new Object());
这是您的代码可能会使用该定义的内容。