可比<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>
, temp
是 Comparable<T>
, 意味着你只能将另一个 T
传递给 compareTo
- 与
T extends Comparable
、temp
是 Comparable
,这意味着您可以将任何内容传递给 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,除非它们想要自定义实现。
我最近为了好玩而编写了一个简单的通用选择排序方法,当我对某些事情有点困惑时。这是我的代码:
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>
,temp
是Comparable<T>
, 意味着你只能将另一个T
传递给compareTo
- 与
T extends Comparable
、temp
是Comparable
,这意味着您可以将任何内容传递给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,除非它们想要自定义实现。