#java #list #коллекции
Есть код: Listc1 = new ArrayList<>( Arrays.asList(new Integer(1394), new Integer(52837)) ); List c2 = Arrays.asList(new Integer[c1.size()]); Как мы вообще присваиваем c2 значение? На что мы ссылаемся, если Array.asList(T... a) возвращает List ? Я даже не понимаю, что это за странный тип возвращаемого значения. Мораль в том, что возвращается некоторый List, но List — это интерфейс. Значит, мы получим ссылку на объект, для которого определено действие .add(E o); Но почему-то вызов c2.add в данном случае вызывает ошибку. Почему так?
Ответы
Ответ 1
Arrays.asList - возвращает список фиксированного размера. Поэтому нельзя ни добавлять, ни удалять. Чтобы как-то манипулировать элементами, придется оборачивать в новый список без фиксированного размера: // Listc2 = new ArrayList (Arrays.asList(new Integer[c1.size()])); List c2 = new LinkedList (Arrays.asList(new Integer[c1.size()])); Если углубиться: Во внутренностях метод Arrays.asList возвращает следующее: return new ArrayList<>(a); но(!!!) возвращает он ArrayList не тот, который находится в пакетеjava.util.ArrayList а тот, который определен как внутренний класс внутри самого java.util.Arrays;. Выглядит он так: private static class ArrayList extends AbstractList implements RandomAccess, java.io.Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; //.... и т.д. реализация } Как видим, эта внутренняя реализация наследуется от AbstractList, в котором по дефолту определены некоторые методы в таком виде public boolean add(E e) { add(size(), e); return true; } public void add(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); } Вот и получается, что вроде как вернули ArrayList, но на самом деле не тот лист, который ожидали (java.util.ArrayList), а эмуляцию. О том, что такое и List стоит прочитать материалы на тему generics или обобщений. Тема очень широкая. Ответ 2
Метод Arrays.asList возвращает список фиксированного размера. А именно объект типа java.util.Arrays.ArrayList. Не стоит путать его с обычным, изменяемого размера списком java.util.ArrayList. Данный класс (Arrays.ArrayList) служит "мостом" между взаимодействием с элементами как с массивом и как со списком. Неизменяемость размера списка достигается пробрасыванием UnsupportedOperationException при попытке добавить или удалить элемент в список. Безусловно, это не идеальное решение, особенно если такой список будет передан в метод, который и знать не знает, что это "особенный" список, у которого нельзя вызывать методы add и remove, и просто работает с ним через контракт интерфейса List. Но зато оно позволяет просто и эффективно передать массив в метод, который принимает на вход список/коллекцию и не изменяет размер переданного списка (как правило, используя список только для чтения). Фиксированный размер списка и прямая связь с исходным массивом позволяют сэкономить память и время, так как нет необходимости создавать дополнительный массив и копировать в него элементы из исходного массива. В прямой связи с исходным массивом можно убедиться на следующем примере: Integer[] array = { 1, 2, 3 }; Listlist = Arrays.asList(array); list.set(0, 10); System.out.println(Arrays.toString(array)); [10, 2, 3] - это generics-тип. Соответственно, если в качестве значений в метод Arrays.asList вы передаёте Integer, то и результирующий список будет иметь тип Integer (List ).
Комментариев нет:
Отправить комментарий