2010-04-23 11 views
6

Jaki jest poprawny typ argumentu metody addAll (..) w kolekcjach Java? Jeśli zrobię coś takiego:Generics java i metoda 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); 

Rozumiem, że muszę zainicjować obie zmienne. Dostaję jednak błąd kompilacji (od 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[]>>) 

co robię źle?

+1

Czy możesz edytować, aby pokazać swoje deklaracje dla "currentList" i "newElements"? – elduff

+0

Myślę, że "newElements" ma być "addAll" Naprawiłem kod. – Jherico

Odpowiedz

7

Można jedynie wstawić instancje od T do List<T>.

Typ List<? extends Map<X,Y>> stoi na listy z nieznany typu T który extends Map<X,Y>. Na przykład może oznaczać List<LinkedHashMap<X,Y>>. Oczywiście nie możesz wstawić zwykłej nazwy HashMap<X,Y> do takiej listy.

Prawdopodobnie chcesz:

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

Albo jeśli chcesz być naprawdę elastyczny można zrobić:

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

Które pozwalają robić szalone rzeczy jak:

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

Możesz również przeczytać Ogólne pytania Angeliki Langer, w szczególności the section about wildcards.

0

Twoje pytanie w zasadzie sprowadza się do tego:

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

ten nie powiedzie się z zasadniczo takim samym błędem jak opisujesz. Spróbuj czegoś wzdłuż tych linii, aby to naprawić.

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

Alternatywnie, w powyższym przykładzie można zmienić

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

do

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

Generics ją owłosione dość szybko, jeśli starają się rozpocząć przechodząc wokół nieokreślonych typów.

1

Nie można wywołać żadnej metody z ogólnymi atrybutami na takiej liście. Zasadniczo, co mówi ? extends Foo "coś, co rozszerza Foo", ale nie wiesz, co to jest. Po zwróceniu tego typu można powiedzieć, że zwrócona wartość to Foo lub jakiś podtyp. Ale dla jakiejkolwiek wartości nie możesz tego, że pasuje do standardu ? extends Foo.

W skrócie: trzeba zmienić currentList deklarację lub miotać List (bez rodzajowych) i żyć z ostrzeżeniem lub (jeśli wiesz co robisz) tłumić go.

8

Wymień extends przez super.

Samo ustawienie addAll() przyjmuje argument ? extends T, który nie zadziała, gdy T jest ? extends Map<K, V>. Wraz ze zmianą stanie się to skutecznie ? extends ? super Map<K, V>.

Ale nadal lepiej jest usunąć ten ? extends (lub ? super). W tym konkretnym przypadku jest zbędne. Po prostu użyj List<Map<String, Object[]>>. Model addAll() będzie wówczas skutecznie pobierał ? extends Map<String, Object[]>>.

+0

dlaczego nawet zadeklarować 'currentList' jako' List > ', a nie tylko' List > '? ta część jego kodu wydaje mi się niepotrzebna. –

+0

@matt: Tak też powiedziałem w poprzednim akapicie :) – BalusC

6

tylko pamiętaj:

dla <? extends ...>, nie można umieścić rzeczy (oprócz null) do niego

dla <? super ...>, nie można dostać rzeczy (poza obiektem) z niego