Почему мы не можем увеличить размер объекта ArrayList, возвращаемого asList ()?

#java #arrays #list #arraylist

#java #массивы #Список #arraylist

Вопрос:

Я проходил через реализацию Arrays.asList() .Если мы попытаемся изменить размер массива с помощью List(I) определенных методов, то получим RE: UnsupportedException . Реализация —

 public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}
  

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

В частности, что мешает изменить размер возвращаемого ArrayList объекта?

Любые предложения были бы полезны и оценены.

Комментарии:

1. Вы уверены, что используется именно такая перегрузка? Он имеет несколько iirc.

2. Да, это то, что указано в java.util. Массивы;

3. Вот результат, который я вижу, когда смотрю на исходный код: return new Arrays.ArrayList(a) . Это не обычный ArrayList.

4. Это другой класс, который просто случайно также вызывается ArrayList .

5. System.out.println(asList().getClass()) .

Ответ №1:

List Возвращаемый Arrays.asList() объект частично неизменяем. Некоторые операции мутации реализованы, другие — нет. В принципе, все операции, которые выполняют запись в базовый массив, реализованы. Операции, которые потребовали бы перераспределения нового массива, не реализованы. set() например, реализовано, add() нет. Если вам нужен правильный List изменяемый во всех аспектах:

 List<T> myList = asList(v1, v2, v3); // Immutable
List<T> myList = new ArrayList<>(asList(v1, v2, v3)); // Mutable
  

Объект, List возвращаемый Arrays.asList() , не является «нормальным» (java.util.)ArrayList . Обычный объект ArrayList может увеличиваться за счет перераспределения его резервного массива, что означает, что он является надлежащим, List поддерживаемым массивом, но со всеми List доступными функциями.

List Возвращаемое Arrays.asList() является « List представлением» исходного массива. Он не может увеличиться, потому что это привело бы к потере ссылки на исходный массив. Следующий код демонстрирует это:

 String[] data = { "foo", "bar" };
List<String> values = Arrays.asList(data);
System.err.println(values); // [foo, bar]
data[0] = "buzz";
values.set(1, "quak");
System.err.println(values); // [buzz, quak]
System.err.println(Arrays.toString(data)); // [buzz, quak]
  

Комментарии:

1. Это не изменчиво. Вызов set() вызовет исключение.

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

3. Ya. Я искал здесь: hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/be44bff34df4/src/share /…

4. Это не противоречит. В Arrays.asList документации говорится, что » возвращает список фиксированного размера, поддерживаемый указанным массивом «. Методы add и remove по своей сути требуют списка переменного размера. Причина, по которой вы можете использовать set get ), заключается в том, что это похоже на доступ к массиву через индекс, за исключением того, что вместо массива это List . Это несколько объясняется AbstractList : » Чтобы реализовать изменяемый список, [вы] должны дополнительно переопределить метод set(int, E) [. . .] Если список имеет переменный размер [вы] должны дополнительно переопределить методы add(int, E) и remove(int). «.

5. @Slaw Спасибо за ваши указания, я соответствующим образом обновил ответ.