Java Generics: compareTo 和 “capture#1-of ?”

2022-09-04 19:28:25

下面给了我一条错误消息:

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


答案 1

List<?>表示“任何东西的列表”,所以具有此类型的两个对象是不相同的:一个可以是 的列表,另一个可以是 的列表。显然,这些是不一样的。StringBigDecimal

List<T>意思是“列出任何东西,但当你再次看到时,它是一样的”。TT

当您在不同的地方表示相同的类型时,您必须告诉编译器。尝试:

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>TComparable<? super T>Comparable<X>XT

? super T表示必须支持的类型或其超类型之一。ComparableT

想象一下这个继承:.这在Java中是不正确的,但想象一下这只是一个加一小部分。在此方案中,一个 适用于 也适用于 和 因为两者都派生自 。因此,将满足作为 、 或 的部分。Double extends Integer extends NumberDoubleIntegerComparableNumberIntegerDoubleNumberComparable<Number>superTNumberIntegerDouble

只要这些类型中的每一种都支持接口,它们也满足声明的第一部分。这意味着,您可以传入 for,并且当列表中有和实例时,生成的代码也将起作用。如果你支持 ,你仍然可以使用,但是不可能的,因为它不再满足了(不过,这部分仍然有效)。ComparableNumberTIntegerDoubleIntegerTDoubleNumberT extends Comparablesuper

下一步是了解 和 之间的表达式只是声明稍后在代码中使用的类型的属性。这样,您就不必一遍又一遍地重复这个长篇大论。它是方法行为的一部分(如 ),而不是实际代码的一部分。staticListTpublic


答案 2

推荐