Частный статический класс ArrayList в java.util.Arrays - Почему?

В java.util.Arrays определен частный статический класс с именем "ArrayList". Он ссылается только на метод Arrays.asList.

Какова польза от этого? Почему java.util.ArrayList не упоминается вместо этого?

Код ниже:

   /**
    * @serial include
    */
      private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable

Ответ 1

В чем преимущество этого? Почему вместо java.util.ArrayList не указано?

Одна из причин заключается в том, что фактический класс реализации не является публичной информацией API. Это означает, что они могут изменить класс реализации в будущем... без риска нарушения кода клиента.

Другая причина для этого заключается в том, что этот частный класс реализует некоторые операции по-разному с ArrayList. В частности, операции, связанные с изменением размера списка, должны быть реализованы для генерирования исключения... для того, чтобы соответствовать поведению, указанному в javadocs для метода Arrays.asList(...).

В действительности, список, возвращаемый Arrays.asList(...), является оболочкой для исходного массива, а не полным списком функций. Это имеет свои преимущества и недостатки:

  • В нижней части некоторые операции не работают.

  • В верхней части создание обертки намного дешевле, чем создание первого класса из массива. (Последнее влечет за собой копирование содержимого массива в список... и это будет дорого для большого массива.)

Кроме того, есть проблема, что изменения в исходном массиве видны через оболочку (и наоборот)... что может быть полезно, если это то, что вам нужно.


Вы спросили об этом в комментарии:

a) Зачем возвращать список без изменения размера?

Поскольку возврат регулярного измененного размера списка влечет за собой скопирование содержимого массива в какой-то момент... что дорого. (И если реализация отложила копирование до тех пор, пока не будет выполнена операция изменения размера, связь между исходным массивом и списком будет очень трудно понять. Подумайте об этом...)

b) Почему бы не использовать Collections.unmodifiableList и передать объект java.util.ArrayList?

Это ничего не добивается. Вам все равно нужно скопировать содержимое массива в ArrayList. Весь смысл этой "странной" поведенческой спецификации заключается в том, чтобы избежать необходимости копировать.

Ответ 2

Несмотря на то, что класс private static ArrayList имеет то же имя, что и java.util.ArrayList, они ведут себя по-разному по дизайну. Учитывая это, нет никакой причины, что реализации должны быть одно и то же.

Arrays#asList() возвращает список фиксированного размера, поддерживаемый указанным массивом. (Изменения в возвращенном списке "write through" для массива.) Этот метод действует как мост между API-интерфейсами на основе массивов и коллекций.