可比<T> 与原始可比

Comparable<T> vs Raw Comparable

我最近为了好玩而编写了一个简单的通用选择排序方法,当我对某些事情有点困惑时。这是我的代码:

public static <T extends Comparable<T>> void sort(List<T> list) {
    for (int i = 0; i < list.size(); i++) {
        int minIndex = i; // Assume that the first element is the minimum for now.

        // Find smallest element in unsorted sub-list.
        for (int k = i + 1; k < list.size(); k++) {
            if (list.get(k).compareTo(list.get(minIndex)) < 0) {
                minIndex = k;
            }
        }

        // Swap smallest element with the first element in unsorted sub-list.
        T temp = list.get(i);
        list.set(i, list.get(minIndex));
        list.set(minIndex, temp);
    }
}

函数本身工作正常,但我对泛型有点困惑。我使用:

<T extends Comparable<T>>

确保给定的列表具有可比较的类型。但是如果我改用原始的 Comparable 呢?即:

<T extends Comparable>

具体会有什么影响?

谢谢!

<T extends Comparable> 适用于混合类型的可比对象。例如,Integer 实例和 String 实例都可以满足,而 <T extends Comparable<T>> 确保类型可以相互比较。

举个例子,下面会编译但会因为 class 转换异常而抛出运行时异常:

public static void main(String[] args)
{
    List<? extends Comparable> l = createList(Integer.valueOf(1), "Man");
    Collections.sort(l);
}

protected static <T extends Comparable<?>> List<T> createList(T ... args)
{
    return Arrays.asList(args);
}

通过限制为 <T extends Comparable<T> 这变成了运行时检查,因为将方法更改为此会阻止以前的代码编译。

基本上,你失去了一些类型安全。

当您拥有 T temp = list.get(i) 后,您可以用 temp.compareTo 做什么?

  • with T extends Comparable<T>, tempComparable<T>, 意味着你只能将另一个 T 传递给 compareTo
  • T extends ComparabletempComparable,这意味着您可以将任何内容传递给 compareTo

第一个几乎肯定是您想要的,因为可比较类型只能处理相同类型的对象。例如,String.compareTo 只能处理字符串输入——如果你传入一个整数,你将得到一个 ClassCastException。

鉴于 temp.compareTo 的唯一安全输入是类型 T 的引用,通常没有充分的理由使用原始类型。 偶尔 有利于绕过类型系统,但在大多数情况下,它会消除类型安全性,而不会在 return.

中给你任何东西

另一个结果可能是继承一个超级 class,它将实现非泛型 Comparable(obj)。

public abstract Ship implements Comparable {
  public int compareTo(obj) {
    return ..
  }
}

那么 subclass 也必须实现自己的 Comparable。没有它像这样:

public class Boat extends Ship {}

编译器会在 Boat 上抱怨:

Boat is not abstract and does not override abstract method compareTo(java.lang.Object) in java.lang.Comparable

虽然使用具有特定类型的泛型版本,当 compareTo(T obj) 将存在于抽象 class T 中时,继承 classes 将不必实现自己的 compareTo,除非它们想要自定义实现。