Проблема с дженериками - PullRequest
0 голосов
/ 18 января 2011

У меня есть следующие утверждения:

    List<List<String>> myList  = new ArrayList<ArrayList<String>>();

    List<ArrayList<String>> myList  = new ArrayList<ArrayList<String>>();

Первый из них дает ошибку компиляции. Разве мы не должны кодировать интерфейс? Здесь я вынужден кодировать классом, а не интерфейсом. Это ошибка дженериков, или я неправильно ее понимаю?

Ответы [ 5 ]

5 голосов
/ 18 января 2011

Должно быть:

List<List<String>> myList = new ArrayList<List<String>>();

Вам необходимо передать тип, который может быть интерфейсом, в конструктор ArrayList. Другими словами, вы хотите ArrayList, который содержит объекты типа List<String>. Затем, когда вы на самом деле помещаете вещи в список:

mList.add(new ArrayList<String>());
3 голосов
/ 18 января 2011

Первый должен быть:

List<List<String>> myList  = new ArrayList<List<String>>();

Семантика следующая: тип myList представляет собой List, связывающий объекты типа List<String>. Класс реализации - это ArrayList, способный содержать объекты типа List<String>.

Как только вы захотите добавить объект в myList, вы можете сделать это следующим образом:

myList.add(new ArrayList<String>());
2 голосов
/ 18 января 2011

Это известная проблема.Если вы сделаете это, у вас будут другие проблемы.

Рассмотрите этот код:

List<List<String>> myList  = new ArrayList<ArrayList<String>>();
myList.push( new LinkedList<String>() );   // impossible to catch, because java don't have generic in runtime

ArrayList<ArrayList<String>> list2 = (ArrayList<ArrayList<String>>) myList; // ok

ArrayList<String> something = list2.get(0);  // doh! impossible to assign LinkedList to ArrayList
1 голос
/ 21 января 2011

Вы можете сделать это: List<? extends List<String>> myList = new ArrayList<ArrayList<String>>();

Причина, по которой ваша первая строка не работает, заключается в том, что вы не можете выполнить List<A> = List<B>, даже если B является подтипом A (как и здесь, ArrayList является подтипом List). В противном случае это нарушит безопасность типов. Это базовая функция Generics, с которой у многих новичков возникают проблемы. Тем не менее, вы можете сделать List<? extends A> = List<B>; в этом случае ? extends A является групповым символом, который может включать B . В обмен вы теряете возможность добавлять вещи в List<? extends A> (Правило: расширяет производителя, супер-потребителя), и это устраняет проблему безопасности.

1 голос
/ 18 января 2011

Проблема здесь немного тонкая.Чтобы исправить это, вам нужно:

List<List<String>> myList = new ArrayList<List<String>>();

В определении myList запрашивается список списков строк , но вы реализуете его как ArrayListArrayLists of Strings , и они не совпадают.Это станет проблемой, если позже вы попробуете что-то вроде:

myList.add(new LinkedList<String>());

Это нормально по определению Список списков строк , но нарушает определение реализации.LinkedList является списком , но не является списком ArrayList.

Если вы хотите установить, что это ArrayList ArrayLists of Strings ,тогда вы можете использовать определение ArrayList<ArrayList<String>> myList, но обычно лучше придерживаться интерфейсов.

С моим пересмотренным кодом вы все равно можете сделать его в реализации ArrayList из ArrayLists of Strings.

List<List<String>> myList = new ArrayList<List<String>>();
for (int i = 0; i < rowSize; i++)
{
 myList.add(new ArrayList<String>());
}

Это согласуется с определением myList как Список списков строк , но вы все равно получаете преимущества от использования ArrayList за кулисами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...