为什么我在使用Collections.sort()时遇到编译时错误,但是没有使用TreeSet.add(new Object())

时间:2013-01-25 14:26:24

标签: java

为什么我被允许这样做:

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

但不是这样:

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

第一个给了我一个ClassCastException,但第二个给了我一个编译错误。据我了解,实际问题在两种情况下都是相同的:java.lang.Object未实现可比较界面。

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

更新#2: 根据java版本,我得到不同的结果。请看图片: enter image description here

4 个答案:

答案 0 :(得分:5)

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

SortedSet界面不会强制您将其通用类型指定为Comparable,因为TreeSet还允许您为不Comparator的类型指定Comparable 1}}。编译器无法区分这两个选项。

答案 1 :(得分:4)

Collections.sort需要Comparable列表。 TreeSet在输入时没有这个限制。使用默认构造函数,文档说它按“元素的自然排序”进行排序。不清楚的是它如何排序Object,但你的问题涉及打字。

更新: 我错过了问题的最后部分。在没有查看堆栈跟踪的情况下,我猜想由于TreeSet的默认构造函数尝试按“自然顺序”排序,在内部,它正在执行转换为Comparable,这会导致{{1} }}

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

  

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

两者兼而有之。因此,如果JDK6没有发生ClassCastException,也许这是一个错误。

答案 2 :(得分:4)

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

Collections.sort(T)需要T实施ComparableCollections中有另一种接受任何对象的方法,但您需要提供Comparator

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

答案 3 :(得分:2)

从Collection:

中查看sort函数的签名
public static <T extends Comparable<? super T>> void sort(List<T> list)

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

但是在Treeset的情况下,添加的元素没有限制应该实现Comparable.It只需要正常工作。