Должен ли я объявлять/инициализировать ArrayLists как списки, ArrayLists или ArrayLists <Cat>

В чем разница в объявлении коллекции как таковой

public class CatHerder{
    private List cats;
    public CatHerder(){
        this.cats = new ArrayList<Cat>();
    }
}
//or
public class CatHerder{
    private ArrayList cats;
    public CatHerder(){
        this.cats = new ArrayList();
    }
}
//or
public class CatHerder{
    private ArrayList<Cat> cats;
    public CatHerder(){
        this.cats = new ArrayList<Cat>();
    }
}

Ответ 1

Вы должны объявить его как List<Cat> и инициализировать его как ArrayList<Cat>.

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

В зависимости от того, как вы на самом деле используете этот список, вы даже можете использовать менее конкретный java.util.Collection (интерфейс, который List расширяет).

Что касается List<Cat> (вы можете прочитать это как "список кошек" ) vs List: что Java generics, которые обеспечивают время компиляции типа безопасно. Короче говоря, он позволяет компилятору убедиться, что List содержит только объекты Cat.


public class CatHerder{
    private final List<Cat> cats;
    public CatHerder(){
        this.cats = new ArrayList<Cat>();
    }
}

Ответ 2

Я бы сделал следующее.

public class CatHerder{
    private final List<Cat> cats = new ArrayList<Cat>();
}

Ответ 3

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

Тем не менее, если вы не используете что-то конкретное для класса ArrayList, вы должны использовать List<Cat>, чтобы не связывать ваш код с конкретной реализацией List.

Ответ 4

Как уже сказал Мэтт, использование наиболее распространенного интерфейса/суперкласса - лучший способ пойти сюда. Обязательно всегда указывайте тип, который отображается в вашем списке, поэтому сделайте его List<Cat> или даже List<? extends Cat>

Если в какой-то более поздний момент вы захотите заменить ArrayList на, скажем, на LinkedList, вам не придется изменять объявление, а только экземпляр.

Ответ 5

List более гибкий, чем ArrayList, List<Cat> безопаснее, чем List. поэтому List<Cat> - хороший выбор.

Ответ 6

Прежде всего, List - это интерфейс, а ArrayList - это реализация интерфейса List (на самом деле это подклассы AbstractList и implements List). Поэтому List cats = new ArrayList() справедливо, так как ArrayList is-a List.

Для этого:

private List cats;

cats становится сырым типом (нет ссылки на Generic Type для List), он не был параметризован.

Ваше третье решение правильно (оно решает вашу проблему для варианта 1),

private ArrayList<Cat> cats;

вы ограничили общий тип E для List<E> типом Cat. Следовательно, ваш экземпляр cats действителен, так как общее ограничение является одинаковым.

Второе решение позволяет создать только ArrayList of cats. Другие 2 варианта позволяют вам создать экземпляр любого объекта, который есть-a List, например. LinkedList.