Collections.sort没有编译时错误

时间:2014-10-29 10:27:29

标签: java sorting collections comparable

Collections.sort(list)Collections.sort(list,null)之间有什么区别 我猜他们都按照自然顺序比较了列表中的元素。

所以我尝试了这两个代码:

代码1:

List<Object> list=Arrays.asList("hello",123);
Collections.sort(list);

代码2:

List<Object> list=Arrays.asList("hello",123);
Collections.sort(list,null);

后者编译但前者没有给出预期的编译器错误,即Object类的实例不具有可比性。 为什么后者不会给编译时错误。

编辑:根据以下评论。我理解为什么后者不会给出编译时错误但是在运行它时会抛出ClassCastException : String cannot be converted into Integer。它如何推断出运行时对象是String和Integer,因为我认为

public static sort(List<Object> list)  ---> Since list was of type object
{
// For instances of object in list call the compareTo method 
}

}

4 个答案:

答案 0 :(得分:2)

在编译时检查Java的泛型类型。如果违反约束,您甚至无法编译。第一种方法定义为:

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

这要求您使用的List类型为extend Comparable,特别是某些Comparable<X>,其中X可能是T的任何超类。听起来很复杂但不均匀这里很重要(如果您对该部分感兴趣,请尝试理解http://yzaslavs.blogspot.de/2010/07/generics-pecs-principle-step-by-step.html)。 List<Object>已经与第一部分不匹配。 Object未实施任何Comparable。 =&GT;编译器说没有。

第二个定义为

<T> void sort(List<T> list, Comparator<? super T> c)

不再要求List的类型具有任何特殊属性。任何T都会起作用。唯一的要求是您可以提供能够对T或超类型进行排序的Comparator实现。 null就像一个小丑,适合任何。即使使用null可能错误,编译器也不会抱怨。您确实在运行时看到了问题。


原因

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at java.lang.Integer.compareTo(Integer.java:52)
    at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290)
    at java.util.ComparableTimSort.sort(ComparableTimSort.java:157)
    at java.util.Arrays.sort(Arrays.java:537)
    at java.util.TimSort.sort(TimSort.java:178)
    at java.util.TimSort.sort(TimSort.java:173)
    at java.util.Arrays.sort(Arrays.java:659)
    at java.util.Collections.sort(Collections.java:217)
    at Main.main(Main.java:9)

是&#34; TimSort.java:178&#34;它确实

static <T> void  sort(T[] a, int lo, int hi, Comparator<? super T> c) {
    if (c == null) {
        Arrays.sort(a, lo, hi);
        return;
    }

会像第一次通话那样回归自然排序。然而,在那一点上它只是一个Object[]数组,没有什么能保证类型实际上是可比较的。它只是根据你的运气而放置类型并失败。列表的内容在Integer.compareTo()或String.compareTo()中,因为这些方法需要它们自己的类型。

答案 1 :(得分:1)

Collections

中有两种不同的方法
//here the elements in list should impl. Comparable
Collections.sort(list) 
//here we need a Comparator object, (null is Comparator obj too)
Collections.sort(list, null)

现在谈到运行时类广播问题。

Java将您的列表转换为数组以在后台进行排序。如果Comparator为null,则java会将元素强制转换为Comparable以进行排序。幸运的是,列表中的两个元素(String and Integer)都实现了Comparable。所以直到这里没有例外。

列表中只有两个元素(2 <7 7是insertionsort阈值),因此java只是简单地进行插入排序。取整数,并使用字符串作为参数调用compareTo()方法。这里java将参数转换为Integer,以便它可以比较。正如您所见,String无法转换为Integer,您就会遇到此异常。

答案 2 :(得分:0)

> what is null?

根据JSL -

  

还有一个特殊的null类型,表达式的类型为null,   没有名字。因为null类型没有名称,所以不可能   声明null类型的变量或转换为null类型。   空引用是null表达式的唯一可能值   类型。 null引用始终可以强制转换为任何引用类型。在   实践中,程序员可以忽略null类型而只是假装   null只是一个特殊的文字,可以是任何参考   类型。

由于null可以是任何类型的引用,因此它也可以引用Comparator,这就是编译器接受Collections.sort(list,null);的原因。

Collections.sort(list,new Object());给出编译时异常的地方。


在比较时检查compareTo方法将调用Integer.compareTo方法生成ClassCastException的位置。

答案 3 :(得分:0)

这两者之间没有区别,api doc中明确提到过。 请参阅Collections