[英]Why does the following code sort the List of objects?
你能否解释为什么下面的代码按预期编译和打印[1,2,3,4]。 我正在使用Java 8。
List nums = Arrays.asList(4, 3, 2, 1);
Collections.sort(nums);
System.out.println(nums);
据我所知,这里创建了四个Integer实例。 每个列表条目都包含对Integer实例的Object引用。 由于Object类没有实现Comparable接口,因此Collections.sort应该抛出ClassCastException或类似的东西,因为它无法将Object引用强制转换为Comparable引用。
你能指出我错过了什么吗?
使用1,2,3,4,您将创建int
文字。 在将它们传递给asList(T... a)
它们被装入Integer
对象,这些对象实现Comparable
( public final class Integer extends Number implements Comparable<Integer>
),因此您可以对它们进行排序。
更新
注释:是的,但List被声明为List,因此它是List<Object>
的同义词,而不是List<Integer>
,而Object
不实现Comparable
。
答:您没有为列表指定泛型类型, Collections.sort()
方法仅检查对象的类是否扩展Comparable
。 如果列表没有类型,你的编译器应该只给你一个警告,一切都应该正常工作,因为Integer
是可比的。
排序方法的源代码
public static <T extends Comparable<? super T>> void sort(List<T> list) {
Object[] a = list.toArray();
Arrays.sort(a);
ListIterator<T> i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
}
更新
执行这段代码,看看如果类没有实现Comparable
会发生什么。
public class Test
{
public static void main(String[] args)
{
List objs = new ArrayList<>();
objs.add(new Test());
objs.add(new Test());
Collections.sort(objs);
}
}
在Comparable
第290行中完成的ComparableTimSort.class
将失败!
Exception in thread "main" java.lang.ClassCastException: src.Test cannot be cast to java.lang.Comparable
at java.util.ComparableTimSort.countRunAndMakeAscending(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
at src.Test.main(Test.java:14)
引用的类型与它指向的对象的实际类型之间存在很大差异。
Integer i = 42;
Object o = i;
System.out.println(i.getClass());
System.out.println(o.getClass());
输出:
class java.lang.Integer
class java.lang.Integer
i
和o
指向运行时类型始终为Integer的对象(或值)。 使用更一般类型的引用指向对象不会以任何方式影响其属性或行为。 这就是多态在Java中的工作原理。
因此,这两项任务都有效:
Comparable<Integer> c1 = i;
Comparable<Integer> c2 = (Comparable<Integer>) o;
即使您使用的是原生整数,autobox也会自动将其转换为java.lang.Integer(实现可比较)。 http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html
实际上这是一个铸造问题。 最初创建一个整数数组,然后您已转换为列表。 我希望这个对你有所帮助。
Integer[] number=new Integer[]{4,3,2,1};
Collections.sort(Arrays.asList(number));
System.out.println(Arrays.asList(number));
缺少的部分是类型擦除。
Java编译为JVM字节码,JVM字节码没有泛型概念。 因此,在运行时, List
与List<Comparable>
或List<Object>
完全相同。 如果您的代码曾经包含该信息(您的代码没有),那么在编译代码时它将被删除。
这意味着在运行时, List<Object>
和List<Comparable>
之间没有区别,除了它们包含的实际元素(因此,它也意味着如果你的List
包含任何元素,那么就没有办法了告诉它是什么类型的List
)。
Collections.sort
能够对其元素全部实现Comparable
并且彼此具有Comparable
任何List
进行排序。 由于List
包含实现Comparable
Integer
,因此Collections.sort
能够对其进行排序。
也许是令人困惑的,出于历史原因,这不是阵列的真实情况。 Comparable[]
和Object[]
是完全不同的类型。 原则上,这意味着Java的数组排序方法可能会拒绝对Object[]
数组进行排序,正如您所期望的那样。 实际上它们没有, Arrays.sort
接受Object[]
数组,类似于Collections.sort
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.