дженерики Java и addAll метод

Каков корректный тип аргумента addAll (..) метод в наборах Java? Если я делаю что-то вроде этого:

List<? extends Map<String, Object[]>> currentList = new ArrayList<Map<String, Object[]>>();
Collection<HashMap<String, Object[]>> addAll = new ArrayList<HashMap<String, Object[]>>();
// add some hashmaps to the list..
currentList.addAll(addAll); 

Я понимаю, что должен инициализировать обе переменные. Однако я получаю ошибку компиляции (от затмения):

Multiple markers at this line
    - The method addAll(Collection<? extends capture#1-of ? extends Map<String,Object[]>>) in the type List<capture#1-of ? extends Map<String,Object[]>> is not applicable for the arguments (List<capture#2-of ? extends 
     Map<String,Object[]>>)
    - The method addAll(Collection<? extends capture#1-of ? extends Map<String,Object[]>>) in the type List<capture#1-of ? extends Map<String,Object[]>> is not applicable for the arguments 
     (Collection<HashMap<String,Object[]>>)

что я делаю неправильно?

7
задан skaffman 9 June 2010 в 20:41
поделиться

5 ответов

Вы можете вставлять только экземпляры T в List .

Тип Список > обозначает список неизвестного типа T , который расширяет Map . Например, он может обозначать List > . Очевидно, вы не можете вставить обычный HashMap в такой список.

Вы, вероятно, захотите:

List<Map<String, Object[]>> currentList;

Или, если вы хотите быть действительно гибким, вы можете сделать:

List<? super Map<String, Object[]>> currentList;

Что позволит вам делать сумасшедшие вещи вроде:

currentList = new ArrayList<Map<? super String, ? extends Object[]>>();

Вы также можете прочитать FAQ по обобщениям Анжелики Лангер, в частности раздел о шаблонах .

7
ответ дан 6 December 2019 в 08:14
поделиться

Ваш вопрос в основном сводится к следующему:

public static <T extends Collection<?>> void foo(T t) {
T x = null;
x.addAll(t);
}

Это приведет к сбою, по сути, с той же ошибкой, которую вы описываете. Попробуйте что-нибудь в этом роде, чтобы исправить это.

public static <T extends Collection<Y>, Y> void foo(T t) {
T x = null;
x.addAll(t);
}

В качестве альтернативы, в приведенном выше примере вы можете изменить

List<? extends Map<String, Object[]>> currentList;

на

List<Map<String, Object[]>> currentList;

Generics довольно быстро становится волосатым, если вы пытаетесь начать передавать неуказанные типы.

0
ответ дан 6 December 2019 в 08:14
поделиться

Заменить extends на super .

Сам addAll () принимает ? расширяет аргумент T , и это не сработает, когда T равно ? расширяет Map . С изменением станет эффективно ? расширяется? супер Карта .

Но все же лучше просто удалить это ? расширяет (или ? super ). В данном конкретном случае это лишнее. Просто используйте List > . Тогда addAll () будет эффективно принимать ? расширяет Map > .

8
ответ дан 6 December 2019 в 08:14
поделиться

В таком списке нельзя вызывать какой-либо метод с универсальными атрибутами. Собственно, что ? extends Foo говорит, что это «что-то, что расширяет Foo », но вы не знаете, что это такое. Когда этот тип возвращается, вы можете сказать, что возвращаемое значение - Foo или какой-то подтип. Но для любого заданного значения вы не можете, чтобы оно соответствовало ? расширяет Foo generic.

Вкратце: вам нужно изменить объявление currentList или преобразовать его в List ( без дженериков) и жить с предупреждением или (если вы знаете, что делаете) подавите это.

1
ответ дан 6 December 2019 в 08:14
поделиться

просто запомните:

для ] , вы не можете помещать в него вещи (кроме null)

for , вы не можете получить от него что-либо (кроме объекта)

6
ответ дан 6 December 2019 в 08:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: