2010-04-23 11 views
6

Qual è il tipo corretto di argomento per il metodo addAll (..) nelle raccolte Java? Se faccio qualcosa del genere:java generics e il metodo 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); 

Capisco che ho bisogno di inizializzare entrambe le variabili. Tuttavia, ottengo un errore di compilazione (da eclissi):

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

cosa sto facendo male?

+1

È possibile modificare per mostrare le dichiarazioni sia per "currentList" che per "newElements"? – elduff

+0

Penso che "newElements" dovrebbe essere "addAll" Ho corretto il codice. – Jherico

risposta

7

È possibile inserire solo istanze di T in un List<T>.

Il tipo List<? extends Map<X,Y>> sta per un elenco di un sconosciuta tipo T che extends Map<X,Y>. Ad esempio, potrebbe rappresentare un List<LinkedHashMap<X,Y>>. Ovviamente, non è possibile inserire un ordinario HashMap<X,Y> in tale elenco.

Probabilmente si desidera:

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

Oppure, se si vuole essere veramente flessibile che si possa fare:

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

che permetterebbe di fare cose folli come:

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

Si potrebbe anche voler leggere le FAQ generiche di Angelika Langer, in particolare the section about wildcards.

0

La tua domanda si riduce essenzialmente a questo:

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

Questo non riuscirà con essenzialmente lo stesso errore, come si descrive. Prova qualcosa in questo modo per risolverlo.

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

In alternativa, nel tuo esempio sopra si potrebbe cambiare

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

a

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

Generics ottiene peloso abbastanza rapidamente se si tenta di avviare passando intorno tipi non specificati.

1

Non è possibile chiamare alcun metodo con attributi generici in tale elenco. Fondamentalmente, ciò che dice ? extends Foo è "qualcosa che si estende Foo", ma non sai cosa sia quel qualcosa. Quando viene restituito quel tipo, puoi dire che il valore restituito è Foo o qualche sottotipo. Ma per ogni dato valore non è possibile che corrisponda allo ? extends Foo generico.

In breve: è necessario cambiare currentList dichiarazione o gettarlo ai List (senza generici) e vivere con un avvertimento o (se si sa cosa si sta facendo) sopprimerla.

8

Sostituire extends entro il super.

Lo addAll() prende un argomento ? extends T e che non funzionerà quando T è ? extends Map<K, V>. Con il cambiamento diventerà effettivamente ? extends ? super Map<K, V>.

Ma ancora, meglio è solo per rimuovere quello (o ? super). È superfluo in questo caso particolare. Basta usare List<Map<String, Object[]>>. Lo addAll() prenderà quindi effettivamente il valore ? extends Map<String, Object[]>>.

+0

perché dichiarare anche 'currentList' come' Elenco > ', e non solo' List > '? questa parte del suo codice mi sembra non necessaria. –

+0

@matt: questo è anche quello che ho detto nell'ultimo paragrafo :) – BalusC

6

Basta ricordare:

per <? extends ...>, non si può mettere le cose (tranne NULL) in esso

per <? super ...>, non è possibile ottenere le cose (tranne Object) fuori di esso