Вопрос: Почему класс arraylist реализует List, а также расширяет AbstractList?


Реализация java.util.ArrayList инвентарь List а также расширяет AbstractList, Но в java-документах вы можете видеть, что AbstractList уже реализует List. Тогда не было бы лишним реализовать List, а также расширить AbstractList?
Мой второй вопрос

Пожалуйста, ознакомьтесь со следующим кодом:

String str = "1,2,3,4,5,6,7,8,9,10";
String[] stra = str.split(",");
List<String> a = Arrays.asList(stra);

Arrays.asList() метод класса Arrays содержит собственную реализацию ArrayList. Но это только расширяет AbstractList, но не реализует List. Но приведенный выше код компилируется.
НО, когда код изменен на следующий

String str = "1,2,3,4,5,6,7,8,9,10";
String[] stra = str.split(",");
java.util.ArrayList<String> a = Arrays.asList(stra);

Я получаю сообщение об ошибке: cannot convert form List<String> to ArrayList<String>
В чем причина этого?
РЕДАКТИРОВАТЬ
Arrays.asList() возвращает свою собственную реализацию ArrayList. Проверьте это  вне.


22


источник


Ответы:


Для вашего первого вопроса взгляните на Почему ArrayList имеет «реализует список»?


Чтобы ответить на второй вопрос

java.util.ArrayList<String> a = Arrays.asList(stra);

как вы упомянули Arrays.asList возвращает собственная реализация  от AbstractList и, к сожалению, создатели этого кода также назвали этот класс ArrayList. Теперь, поскольку мы не можем лить горизонтально, но только вертикально возвращенный список массива не может быть отброшен java.utli.ArrayList но только для java.util.AbstractList или его супер типы, такие как java.util.List поэтому ваш первый пример кода работает.


4



Тогда не было бы лишним реализовать List, а также расширить AbstractList?

Да, это на 100% избыточно. Однако разработчики Java добавили интерфейсы очень последовательно во всю публичную реализацию библиотеки коллекций:

  • LinkedList<E> а также ArrayList<E> простираться AbstractList<E> который реализует List<E>, а затем реализовать List<E> самих себя.
  • HashSet<E> а также TreeSet<E> простираться AbstractSet<E> который реализует Set<E>, а затем реализовать Set<E> самих себя.
  • HashMap<K,V> а также TreeMap<E> простираться AbstractMap<K,V> который реализует Map<K,V>, а затем реализовать Map<K,V> самих себя.

Я понимаю, что они сделали это для целей документации: авторы хотели показать, что ArrayList<E> является прежде всего List<E>; дело в том, что ArrayList<E> продолжается AbstractList<E> является менее значительной деталью его реализации. То же самое касается других типов коллекций.

Обратите внимание, что Arrays.ArrayList<E> класс не является общедоступным, поэтому его авторы не хотели включать List<T> в явном виде.

Что касается неудачного преобразования, это не должно удивлять, потому что внутренний класс Arrays.ArrayList<E> и общественный класс ArrayList<E> не связаны друг с другом.


25



Arrays.asList  возвращает Список , Поэтому, бросая его на ArrayList  небезопасно, так как вы не знаете, какой тип Список  (зависит от типа массива, из которого создается список). Ваш второй фрагмент ArrayList  неявно. Следовательно, он терпит неудачу, пока ваш первый фрагмент компилируется отлично, потому что он ожидает Список , Ты можешь сделать-

ArrayList<String> a = new ArrayList<String>(Arrays.asList(stra));

3



Ответ на ваш первый вопрос заключается в том, что реализация List - это контракт. Этот контракт может быть определен как AbstractList, так и ArrayList. ArrayList реализует List для публикации факта, который будет уважать контракт List в будущем, когда может потребоваться продлить не из AbstractList, который может или не может реализовать List.

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


2



Полагаю, есть причина. Это только моя мысль, и я не нашел ее нигде в JLS.

Если я разработчик, который пишет API, который будет широко использоваться, зачем мне это делать?

Нет абсолютно никаких оснований для этого, но рассмотрите этот сценарий, где я написал List интерфейса и ArrayList реализации List интерфейс.

Я еще не написал абстрактного класса AbstractList до настоящего времени.

Однажды возникает требование, когда меня просят написать несколько List интерфейс, в котором большинство из них имеют похожие или одинаковые конкретные методы для abstract методов в List интерфейс.

Я продолжу и напишу AbstractList с необходимой реализацией для всех этих методов. Но теперь мне не понравится эта половина моих классов для реализации List интерфейс и половина из них расширяются AbstractList,

Кроме того, я не могу просто пойти и удалить «реализующий список» из классов, которые я написал ранее, может быть, потому что это не подходящее время, или я не хочу, чтобы код другого пользователя нарушался с моей новой версией.

Заметка  Это единственное мое мнение.


2



1) ArrayList implements List является излишним, но все еще законным. Дизайнеры JCF (Java Collection Framework) могли бы ответить на вопрос. Поскольку ведущий дизайнер JCF Дж.Блоч не говорит, почему это так в «Эффективной Java», похоже, мы никогда не узнаем почему.

2) Возвращает Arrays.asList

public class Arrays {
   ...

    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
...

это не java.util.ArrayList, и его нельзя отбросить


2



Я буду прост и прям в своих ответах.

не было бы избыточным, чтобы реализовать Список, а также расширить   AbstractList?

Да, это так, но они сделали это, чтобы прояснить код, чтобы было легко увидеть, что класс реализует интерфейс List.

Метод Arrays.asList () класса Arrays содержит собственные   реализация ArrayList. Но это только расширяет AbstractList   но не реализует List.

Как вы могли видеть, это было избыточно, вам не нужно повторно объявлять реализацию интерфейса List, если AbstractList уже объявляет эту реализацию.

Я получаю сообщение об ошибке: невозможно преобразовать форму List в ArrayList   В чем причина этого?

Arrays.asList () возвращает список, это может быть любой тип списка. ArrayList, реализованный в этом коде, не является тем же самым ArrayList из java.util.ArrayList, они просто используют одно и то же имя, но это не тот же код.


1



просто хочу дополнить ответы на вопрос 2

java.util.ArrayList<String> a=Arrays.asList(stra);

компилятор просто знает тип возврата Arrays.asList является List, но не знает его точной реализации, которая не может быть java.util.ArrayList, Так вы получили эту ошибку времени компиляции.

Несоответствие типов: невозможно преобразовать из списка в ArrayList

вы можете принудительно заставить верхний текст явно так,

java.util.ArrayList<String> a =(java.util.ArrayList<String>)Arrays.asList(stra);

Код будет скомпилирован успешно, но произойдет исключение во время выполнения,

java.lang.ClassCastException: java.util.Arrays $ ArrayList  не может быть   бросить java.util.ArrayList

это потому что java.util.Arrays$ArrayList (тип реализации, который Arrays.asList возвращает) не является подтипом java.util.ArrayList,


0