Подтвердить что ты не робот

Почему следующий код сортирует список объектов?

Не могли бы вы объяснить, почему следующий код компилирует и печатает [1, 2, 3, 4], как и ожидалось. Я использую Java 8.

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

Как я понимаю, здесь создаются четыре экземпляра Integer. Каждая запись списка содержит ссылку на объект для экземпляра Integer. Так как класс Object не реализует интерфейс Comparable, то Collections.sort должен вызывать ClassCastException или что-то вроде этого, потому что он не может передавать ссылки Object на ссылки Comparable.

Не могли бы вы указать, что мне не хватает?

4b9b3361

Ответ 1

С 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)

Ответ 2

Существует большая разница между типом ссылочного и фактического типа объекта, на который он указывает.

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 указывают на объект (или значение), тип исполнения которого всегда является целым. Указание на объект с использованием ссылки более общего типа никак не влияет на его свойства или поведение. Вот как полиморфизм работает на Java.

Поэтому оба этих задания работают:

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

Ответ 3

Даже если вы используете собственное целое число, автобокс автоматически преобразует его в java.lang.Integer(который реализует сопоставимые). http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html

Ответ 4

На самом деле это проблема кастинга. Сначала создайте целочисленный массив, а затем вы преобразуетесь в список. Я надеюсь, что это поможет вам.

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

Ответ 5

Отсутствующий фрагмент здесь - стирание типа.

Java компилируется в байт-код JVM, а байт-код JVM не имеет понятия дженериков. Поэтому во время выполнения a List точно совпадает с List<Comparable> или List<Object>. Если ваш код когда-либо содержал эту информацию (который не имеет вашего кода), то он удаляется при компиляции вашего кода.

Это означает, что во время выполнения нет никакой разницы между List<Object> и a List<Comparable>, кроме фактических элементов, которые они содержат (как следствие, это также означает, что если ваш List не содержит элементов, тогда никоим образом не сказать, какой тип List он должен был быть).

Collections.sort способен сортировать любые List элементы которого реализуют Comparable и сравнимы друг с другом. Поскольку ваш List содержит Integer s, которые реализуют Comparable, Collections.sort способен сортировать его.

Возможно, смутно, это не относится к массивам по историческим причинам. Comparable[] и Object[] - совершенно разные типы. В принципе, это означает, что методы сортировки массивов Java могут отказаться от сортировки массивов Object[], как вы могли бы ожидать. На практике они этого не делают, и Arrays.sort принимает массивы Object[], аналогично Collections.sort.