简体   繁体   English

为什么以下代码对对象列表进行排序?

[英]Why does the following code sort the List of objects?

Could you please explain why the following code compiles and prints [1, 2, 3, 4], as expected. 你能否解释为什么下面的代码按预期编译和打印[1,2,3,4]。 I'm using Java 8. 我正在使用Java 8。

List nums = Arrays.asList(4, 3, 2, 1);
Collections.sort(nums);
System.out.println(nums);

As I understand, four Integer instances is created here. 据我所知,这里创建了四个Integer实例。 Each list entry contains an Object reference to an Integer instance. 每个列表条目都包含对Integer实例的Object引用。 Since the Object class doesn't implement the Comparable interface, then Collections.sort should throw ClassCastException or something like this because it cannot cast Object references to Comparable references. 由于Object类没有实现Comparable接口,因此Collections.sort应该抛出ClassCastException或类似的东西,因为它无法将Object引用强制转换为Comparable引用。

Could you please point out what I'm missing? 你能指出我错过了什么吗?

With 1,2,3,4 you are creating int literals. 使用1,2,3,4,您将创建int文字。 While passing them to asList(T... a) they get boxed into Integer objects which implements Comparable ( public final class Integer extends Number implements Comparable<Integer> ), so you can sort them. 在将它们传递给asList(T... a)它们被装入Integer对象,这些对象实现Comparablepublic final class Integer extends Number implements Comparable<Integer> ),因此您可以对它们进行排序。

Update 更新

Comment: Yes, but the List is declared as List, so it's the synonym to List<Object> , not List<Integer> , and Object doesn't implement Comparable . 注释:是的,但List被声明为List,因此它是List<Object>的同义词,而不是List<Integer> ,而Object不实现Comparable

Answer: You do not specify a generic type for the list and the Collections.sort() method only checks if the object's class extends Comparable . 答:您没有为列表指定泛型类型, Collections.sort()方法仅检查对象的类是否扩展Comparable If the list has no type, your compiler should only give you a warning and everything should work fine since Integer 's are comparable. 如果列表没有类型,你的编译器应该只给你一个警告,一切都应该正常工作,因为Integer是可比的。

The source code of the sort method 排序方法的源代码

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]);
    }
}

Update 更新

Execute this piece of code to see what happens if the class does not implements Comparable . 执行这段代码,看看如果类没有实现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);
    }
}

The cast to Comparable which is done in Line 290 of ComparableTimSort.class will fail! 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)

There is a big difference between type of a reference and actual type of an object it points to. 引用的类型与它指向的对象的实际类型之间存在很大差异。

Integer i = 42;
Object o = i;
System.out.println(i.getClass());
System.out.println(o.getClass());

Output: 输出:

class java.lang.Integer
class java.lang.Integer

Both i and o point to an object (or value) whose runtime type is always Integer. io指向运行时类型始终为Integer的对象(或值)。 Pointing to the object using a reference of a more general type doesn't affect its properties or behaviour in any way. 使用更一般类型的引用指向对象不会以任何方式影响其属性或行为。 This is how polymorphism works in Java. 这就是多态在Java中的工作原理。

Therefore, both of these assignments work: 因此,这两项任务都有效:

Comparable<Integer> c1 = i;
Comparable<Integer> c2 = (Comparable<Integer>) o;

Even though you are using native integer, the autobox will automatically convert it to java.lang.Integer (which implements comparable). 即使您使用的是原生整数,autobox也会自动将其转换为java.lang.Integer(实现可比较)。 http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html

Actually it is a casting problem. 实际上这是一个铸造问题。 Initially create a integer array and then you have converted into list. 最初创建一个整数数组,然后您已转换为列表。 I hope this one is helpful for you. 我希望这个对你有所帮助。

    Integer[] number=new Integer[]{4,3,2,1};
    Collections.sort(Arrays.asList(number));
    System.out.println(Arrays.asList(number));

The missing piece here is type erasure. 缺少的部分是类型擦除。

Java compiles to JVM bytecode, and JVM bytecode has no concept of generics. Java编译为JVM字节码,JVM字节码没有泛型概念。 So at runtime, a List is precisely the same as a List<Comparable> or a List<Object> . 因此,在运行时, ListList<Comparable>List<Object>完全相同。 If your code ever contained that information (which your code doesn't), then it is erased when your code is compiled. 如果您的代码曾经包含该信息(您的代码没有),那么在编译代码时它将被删除。

This means that at runtime, there's no difference between a List<Object> and a List<Comparable> , other than the actual elements they contain (as a consequence, it also means that if your List contains no elements, then there's no way of telling what sort of List it was meant to be). 这意味着在运行时, List<Object>List<Comparable>之间没有区别,除了它们包含的实际元素(因此,它也意味着如果你的List包含任何元素,那么就没有办法了告诉它是什么类型的List )。

Collections.sort is able to sort any List whose elements all implement Comparable , and are comparable with each other. Collections.sort能够对其元素全部实现Comparable并且彼此具有Comparable任何List进行排序。 Since your List contains Integer s, which implement Comparable , Collections.sort is able to sort it. 由于List包含实现Comparable Integer ,因此Collections.sort能够对其进行排序。

Perhaps confusingly, this isn't true of arrays, for historical reasons. 也许是令人困惑的,出于历史原因,这不是阵列的真实情况。 Comparable[] and Object[] are completely different types. Comparable[]Object[]是完全不同的类型。 In principle, this means that Java's array sorting methods could refuse to sort Object[] arrays, as you might expect. 原则上,这意味着Java的数组排序方法可能会拒绝对Object[]数组进行排序,正如您所期望的那样。 In practice they do not, and Arrays.sort accepts Object[] arrays, analogously to Collections.sort . 实际上它们没有, Arrays.sort接受Object[]数组,类似于Collections.sort

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM