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

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

6 голосов
/ 23 апреля 2010

Каков правильный тип аргумента для метода 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[]>>)

что я делаю не так?

Ответы [ 5 ]

8 голосов
/ 24 апреля 2010

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

Сам addAll() принимает аргумент ? extends T, и он не будет работать, если T равен ? extends Map<K, V>. С изменением оно станет эффективно ? extends ? super Map<K, V>.

Но все же, лучше просто удалить это ? extends (или ? super). Это лишнее в данном конкретном случае. Просто используйте List<Map<String, Object[]>>. addAll() будет эффективно принимать ? extends Map<String, Object[]>>.

7 голосов
/ 24 апреля 2010

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

Тип List<? extends Map<X,Y>> обозначает список неизвестный тип T, который extends Map<X,Y>. Например, это может означать List<LinkedHashMap<X,Y>>. Очевидно, что вы не можете вставить обычный HashMap<X,Y> в такой список.

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

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

Или, если вы хотите быть по-настоящему гибким, вы можете сделать:

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

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

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

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

6 голосов
/ 24 апреля 2010

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

для <? extends ...>, вы не можете положить в него вещи (кроме нуля)

для <? super ...>, вы не можете получить вещи (кроме объекта) из него

1 голос
/ 24 апреля 2010

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

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

0 голосов
/ 24 апреля 2010

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

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;

Дженерики довольно быстро становятся волосатыми, если вы пытаетесь начать обходить неопределенные типы.

...