2010-04-23 20 views
6

¿Cuál es el tipo correcto de argumento para el método addAll (..) en las colecciones de Java? Si hago algo como esto:java generics y el método addAll

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); 

Entiendo que necesito inicializar ambas variables. Sin embargo, aparece un error de compilación (del eclipse):

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[]>>) 

¿Qué estoy haciendo mal?

+1

¿Puede editar para mostrar sus declaraciones tanto para 'currentList' como para 'newElements'? – elduff

+0

Creo que se supone que 'newElements' es 'addAll'. He reparado el código. – Jherico

Respuesta

7

sólo puede insertar instancias de T en un List<T>.

El tipo List<? extends Map<X,Y>> representa una lista de un tipo desconocido T cuales extends Map<X,Y>. Por ejemplo, podría representar un List<LinkedHashMap<X,Y>>. Obviamente, no puede insertar un HashMap<X,Y> ordinario en dicha lista.

Es probable que desee:

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

O si quieres ser muy flexible que podría hacer:

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

lo que permitiría a hacer cosas locas como:

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

Es posible que también desee leer las preguntas frecuentes sobre genéricos de Angelika Langer, particularmente the section about wildcards.

0

Su pregunta básicamente se reduce a esto:

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

Este fallará con esencialmente el mismo error que usted describe. Intenta algo a lo largo de estas líneas para solucionarlo.

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

Como alternativa, en el ejemplo anterior se podría cambiar

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

a

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

Genéricos pone peluda con bastante rapidez si se intenta comenzar a pasar los tipos no especificados.

1

No puede llamar a ningún método con atributos genéricos en dicha lista. Básicamente, lo que ? extends Foo dice es "algo que se extiende Foo", pero no sabes qué es eso. Cuando se devuelve ese tipo, puede decir que el valor devuelto es Foo o algún subtipo. Pero para cualquier valor dado no se puede que coincida con ? extends Foo genérico.

En resumen: Es necesario cambiar currentList declaración o echarlo a List (sin genéricos) y vivir con una advertencia o (si usted sabe lo que está haciendo) suprimirlo.

8

Reemplazar extends por super.

El addAll() toma un argumento ? extends T y eso no funcionará cuando T es . Con el cambio se convertirá efectivamente en ? extends ? super Map<K, V>.

Pero aún así, mejor es solo eliminar ese ? extends (o ? super). Es superfluo en este caso particular. Simplemente use List<Map<String, Object[]>>. El addAll() tomará efectivamente ? extends Map<String, Object[]>>.

+0

¿por qué incluso declarar 'currentList' como' List > ', y no solo' List > '? esta parte de su código me parece innecesaria. –

+0

@matt: Eso también es lo que dije en el último párrafo :) – BalusC

6

sólo recuerda:

para <? extends ...>, no se puede poner las cosas (excepto nula) en ella

para <? super ...>, no se puede conseguir cosas (excepto el Objeto) fuera de él