以下是一条错误消息:
public static List<Comparable<?>> merge(Set<List<Comparable<?>>> lists) {
List<Comparable<?>> result = new LinkedList<Comparable<?>>();
HashBiMap<List<Comparable<?>>, Integer> location = HashBiMap.create();
int totalSize;
for (List<Comparable<?>> l : lists) {
location.put(l, 0);
totalSize += l.size();
}
boolean first;
List<Comparable<?>> lowest; //the list with the lowest item to add
int index;
while (result.size() < totalSize) {
first = true;
for (List<Comparable<?>> l : lists) {
if (! l.isEmpty()) {
if (first) {
lowest = l;
}
else if (l.get(location.get(l)).compareTo(lowest.get(location.get(lowest))) <= 0) { //error here
lowest = l;
}
}
}
index = location.get(lowest);
result.add(lowest.get(index));
lowest.remove(index);
}
return result;
}
错误是:
The method compareTo(capture#1-of ?) in the type Comparable<capture#1-of ?> is not applicable for the arguments (Comparable<capture#2-of ?>)
这里发生了什么?我创建了所有Comparable
的类型,因此我可以调用.compareTo
并对此列表进行排序。我是否错误地使用了泛型?
答案 0 :(得分:22)
List<?>
表示“任何内容列表”,因此具有此类型的两个对象不同:一个可以是String
的列表,另一个可以是BigDecimal
的列表。显然,那些不一样。
List<T>
表示“除了T
再次看到T
之外的任何内容列表”。
当你在不同的地方使用相同的类型时,你必须告诉编译器。尝试:
public static <T extends Comparable<? super T>> List<T> merge(Set<List<T>> lists) {
List<T> result = new LinkedList<T>();
HashBiMap<List<T>, Integer> location = HashBiMap.create();
[编辑]那么<T extends Comparable<? super T>> List<T>
是什么意思?第一部分定义了具有以下属性的类型T
:它必须实现接口Comparable<? super T>
(或Comparable<X>
,其中X
也是根据T
定义的)。
? super T
表示Comparable
支持的类型必须为T
或其中一种超类型。
想象一下这个继承:Double extends Integer extends Number
。这在Java中是不正确的,但想象Double
只是Integer
加上一小部分。在这种情况下,适用于Comparable
的{{1}}也适用于Number
和Integer
,因为它们都来自Double
。因此,Number
会满足Comparable<Number>
super
T
,Number
或Integer
的{{1}}部分。
只要这些类型中的每一个都支持Double
接口,它们也满足声明的第一部分。这意味着,您可以为Comparable
传递Number
,当列表中有T
和Integer
个实例时,生成的代码也会生效。如果Double
为Integer
,您仍然可以使用T
,但Double
不可能,因为它不再满足Number
(T extends Comparable
但是,部分仍然可以工作。
下一步是要了解super
和static
之间的表达式只是声明了代码中稍后使用的List
类型的属性。这样,您就不必一遍又一遍地重复这个长的声明。它是方法行为的一部分(如T
),而不是实际代码的一部分。