使用泛型类实现Comparable接口

27

我想定义一个实现通用Comparable接口的类。而在我的类中,我还定义了一个泛型元素T。为了实现该接口,我将比较委托给了T。以下是我的代码:

public class Item<T extends Comparable<T>> implements Comparable<Item> {

    private int s;
    private T t;

    public T getT() {
        return t;
    }

    @Override
    public int compareTo(Item o) {
        return getT().compareTo(o.getT());
    }
}

当我尝试编译它时,我收到以下错误信息:
Item.java:11: error: method compareTo in interface Comparable<T#2> cannot be applied to given types;
        return getT().compareTo(o.getT());
                     ^
  required: T#1
  found: Comparable
  reason: actual argument Comparable cannot be converted to T#1 by method invocation conversion
  where T#1,T#2 are type-variables:
    T#1 extends Comparable<T#1> declared in class Item
    T#2 extends Object declared in interface Comparable
1 error

有人能告诉我为什么出现这种情况以及如何修复吗?


2
不是很确定,但应该将 compareTo(Item o) 更改为 compareTo(Item<T> o),对吗? - npinti
3
为了获得最佳结果,请使用 <T extends Comparable<? super T>>。这个代码片段的含义是限制类型参数 T 必须是可比较的,并且可以与其父类进行比较。 - newacct
你应该为这个问题选择一个答案。 - Ungeheuer
4个回答

27

Item(没有任何类型参数)是一个原始类型,因此:

  1. We could pass any kind of Item to Item.compareTo. For example, this would compile:

    new Item<String>().compareTo(new Item<Integer>())
    
  2. The method o.getT() returns Comparable instead of T, which causes the compilation error.

    In the example under the 1st point, after passing Item<Integer> to Item.compareTo, we would then erroneously pass an Integer to String.compareTo. The compilation error prevents us from writing the code which does that.

我认为你只需移除原始类型:

public class Item<T extends Comparable<T>>
implements Comparable<Item<T>> {

    ...

    @Override
    public int compareTo(Item<T> o) {
        return getT().compareTo(o.getT());
    }
}

10

您在类定义中使用了原始类型(Item<T>是泛型类型,但您省略了类型参数<T>),请将其更改为:

class Item<T extends Comparable<T>> implements Comparable<Item<T>>

请注意最后一个<T>

然后必须更改compareTo方法:

public int compareTo(Item<T> o) { // again, use generics
    return getT().compareTo(o.getT());
}

1
我认为这样更有意义。我已经编译并测试了以下内容:
class Item<E extends Comparable<E>> implements Comparable<E> {

 private int s;
 private E t;

 public E getE() {
     return t;
 }

 @Override
 public int compareTo(E e) {
     return getE().compareTo(e);
 }

 public int compareTo(Item<E> other)
    {
        return getE().compareTo(other.getE());
    }

 }

请注意,您现在需要有两个compareTo方法。

1
提问者希望通过比较它们的值来使项目可比较。 - Njol
如果T实现了Comparable接口,这在这里是成立的。 - Njol
嗯,请看一下我现在提供的另一个解决方案。 - aditya
你的回答没有多少意义。“我们正在扩展可比较性,而不是实现它。” - 一个实现接口和扩展类。在泛型中,无论哪种情况都使用“extends”。 “因为我们使用了通用类型T,所以我们不能覆盖compareTo方法” - 通用类型不会阻止我们实现接口,例如ArrayList<T>实现了List<T>。 “T可以是任何东西[...]特别是必须是可比较的东西” - 在OP的代码和你的代码中,T已经是可比较的,特别是相对于自身。 - Njol
请看一下当前的答案,我已经完全修改了它。 - aditya
1
那肯定更好。 - Njol

0
我遇到了一个相关的问题,但是找不到确切的答案。
假设你有一个接口。
public interface myInt extends Comparable<myInt>

有一个类MyClass,它实现了myInt

现在你只想比较MyClass对象与MyClass。我们应该如何重写接口和类呢?

答案:

public interface myInt<T extends myInt<T>> extends Comparable<T>
public class MyClass implements myInt<MyClass>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接