4

为什么我可以这样做:

TreeSet<Object> treeSet = new TreeSet<Object>();
treeSet.add(new Object());

但不是这个:

final List<Object> objects = new ArrayList<Object>();
Collections.sort(objects);

第一个给我一个 ClassCastException 但第二个给我一个编译错误。据我了解,两种情况下的实际问题是相同的:java.lang.Object没有实现Comparable接口。

更新:嗯,出于某种原因,这只适用于 Java 7 而不是 6。我是愚蠢还是疲倦?有人可以对此有所了解吗?

更新#2:根据java版本,我得到不同的结果。请看图片: 在此处输入图像描述

4

4 回答 4

5

起初我在这里皱眉,但你是对的。

SortedSet接口不强制您将其泛型类型指定为 is ComparableTreeSet还允许您为Comparator不是的类型指定 a Comparable。编译器无法区分这两个选项。

于 2013-01-25T14:33:18.637 回答
4

Collections.sort需要Comparable's 的列表。 TreeSet打字没有这个限制。使用默认构造函数,文档说它按“其元素的自然顺序”排序。尚不清楚它是如何排序Object的,但您的问题与打字有关。

更新:我错过了问题的最后一部分。如果不查看堆栈跟踪,我猜想由于默认构造函数TreeSet尝试按“自然顺序”排序,因此在内部,它正在执行强制转换Comparable,这将导致ClassCastException.

更新:我仔细查看了TreeSetJDK 6JDK 7)的javadocs,它说

构造一个新的空树集,根据其元素的自然顺序排序。插入集合中的所有元素都必须实现 Comparable 接口。此外,所有此类元素必须相互比较:e1.compareTo(e2) 不得为集合中的任何元素 e1 和 e2 抛出 ClassCastException。如果用户尝试将元素添加到违反此约束的集合中(例如,用户尝试将字符串元素添加到元素为整数的集合中),则 add 调用将抛出 ClassCastException。

对彼此而言。因此,如果 JDK6 没有发生 ClassCastException,则可能是一个错误。

于 2013-01-25T14:33:39.377 回答
4

因为TreeSet<E>不限于实现的对象,Comparable因为您可以通过Comparator<E>.

Collections.sort(T)T实现的需求Comparable。还有另一种方法Collections可以接受任何对象,但您需要提供一个Comparator.

最后,这完全取决于您的对象是否具有自然顺序,因为它们实现Comparable了,或者您为对象提供了Comparator完成工作所必需的条件。

于 2013-01-25T14:33:59.703 回答
2

从 Collection 中查看 sort 函数的签名:

public static <T extends Comparable<? super T>> void sort(List<T> list)

它期望实现 Comparable 接口的对象。这就是为什么,您的代码显示编译时错误。

但是在 Treeset 的情况下,添加的元素应该实现 Comparable 没有任何限制。它仅用于正常工作。

于 2013-01-25T14:36:40.313 回答