Java Generics:compareTo和"capture#1-of?"

Nic*_*ner 13 java generics comparable

以下给出了一条错误消息:

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;
}
Run Code Online (Sandbox Code Playgroud)

错误是:

The method compareTo(capture#1-of ?) in the type Comparable<capture#1-of ?> is not applicable for the arguments (Comparable<capture#2-of ?>)
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?我做了所有类型的Comparable所以我可以调用.compareTo并排序这个列表.我是否错误地使用泛型?

Aar*_*lla 21

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();
Run Code Online (Sandbox Code Playgroud)

[编辑]那是什么<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适用于它的工作Number也适用Integer,Double因为它们都来自Number.因此,Comparable<Number>将满足super一部分TNumber,IntegerDouble.

只要这些类型中的每一个都支持Comparable接口,它们也满足声明的第一部分.这意味着,你可以通过在NumberT当有生成的代码也将工作Integer,并Double在列表中的实例.如果你这样IntegerT,你仍然可以使用,Double但是Number不可能,因为它不再满足T extends Comparable(super尽管这部分仍然有用).

下一步是要理解表达式之间的表达式,static并且List只声明T稍后在代码中使用的类型的属性.这样,您就不必一遍又一遍地重复这个长的声明.它是方法行为的一部分(如public),而不是实际代码的一部分.