【问题标题】:Java Generics: compareTo and "capture#1-of ?"Java 泛型:compareTo 和“capture#1-of ?”
【发布时间】:2009-11-20 14:57:32
【问题描述】:

下面给了我一个错误信息:

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 并对这个列表进行排序。我是否错误地使用了泛型?

【问题讨论】:

  • 其中一些 > 需要是 ,但我现在没有时间将其归类为答案。如果没有其他人,我稍后会回来。

标签: java generics comparable


【解决方案1】:

List&lt;?&gt; 表示“任何事物的列表”,因此具有此类型的两个对象不相同:一个可能是 String 的列表,另一个可能是 BigDecimal 的列表。显然,它们不一样。

List&lt;T&gt; 表示“任何内容的列表,但当你再次看到 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();

[编辑] 那么&lt;T extends Comparable&lt;? super T&gt;&gt; List&lt;T&gt; 是什么意思?第一部分定义了具有以下属性的类型T:它必须实现接口Comparable&lt;? super T&gt;(或Comparable&lt;X&gt;,其中X 也是根据T 定义的)。

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

想象一下这种继承:Double extends Integer extends Number。这在 Java 中是不正确的,但可以想象 Double 只是一个 Integer 加上一个小数部分。在这种情况下,适用于NumberComparable 也适用于IntegerDouble,因为它们都派生自Number。所以Comparable&lt;Number&gt; 将满足super 部分为TNumberIntegerDouble

只要这些类型都支持Comparable 接口,它们也满足声明的第一部分。这意味着,您可以将Number 传递给T,并且当列表中有IntegerDouble 实例时,生成的代码也将起作用。如果您将Integer 用于T,您仍然可以使用Double,但Number 是不可能的,因为它不再满足T extends Comparable(尽管super 部分仍然可以工作)。

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

【讨论】:

  • 我已经修正了我的答案。此代码编译。如果您在使用它时遇到错误,请删除 &lt;? super T&gt; 但它应该可以工作。哦,将LinkedList 替换为ArrayList。它速度更快,使用的内存更少。
  • 您能准确解释一下&lt;T extends Comparable&lt;? super T&gt;&gt; 的含义吗?
  • 你不想知道... ;) 好的,看看我的编辑,但不要太努力去理解。这就是为什么没有人喜欢泛型中的通配符。
猜你喜欢
  • 2023-04-04
  • 2022-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-25
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
相关资源
最近更新 更多