2017-10-18 9 views
0

Ich versuche, eine Methode zu schreiben, die jede List of List als Parameter akzeptiert - unabhängig vom Typ der verschachtelten Liste.
Bei einer Methode, die eine einzelne Liste eines beliebigen Typs verwendet, funktioniert der Platzhaltertyp gut (siehe Beispiel 1). Dieses Konzept erstreckt sich jedoch nicht auf eine Liste von Listen. Wie in Beispiel 2 zu sehen ist, akzeptiert die Methode dann nur Parameter vom Typ List<List<?>>, jedoch nicht von einem bestimmten Typ wie List<List<Integer>>. Beispiel3 verwendet einen Typparameter T und akzeptiert List<List<Integer>>, akzeptiert aber nicht mehr List<List<?>>. Warum ist das und wie kann ich eine Methode schreiben, die sowohl List<List<?>> als auch List<List<Integer>> akzeptiert?Generische Typen und Platzhalter in verschachtelten Listen

public void test() 
{ 
    List<Integer> list1; 
    List<?> list2; 

    example1(list1); // Valid 
    example1(list2); // Valid 

    List<List<Integer>> listOfLists1; 
    List<List<?>> listOfLists2; 

    example2(listOfLists1); // Error 
    example2(listOfLists2); // Valid 

    example3(listOfLists1); // Valid 
    example3(listOfLists2); // Error 
} 

public void example1(List<?> listOfLists) {} 

public void example2(List<List<?>> listOfLists) {} 

public <T> void example3(List<List<T>> listOfLists) {} 
+3

[Diese Frage] (https://stackoverflow.com/questions/12861726/why-cant-you-have-a-listliststring-in-java) geht leicht über die Frage hier . Lange Rede kurzer Sinn, Sie müssen nur 'List > 'für' example2' und ebenso 'List > 'für' example3'. Generika können sehr wählerisch sein. – Obicere

Antwort

1

example2 funktioniert nicht, weil List<List<Integer>> kein Subtyp von List<List<?>> selbst ist aber List<Integer> ist ein Subtyp von List<?>, ähnlich wie List<String> ist kein Subtyp von List<Object> obwohl String ist ein Subtyp von Object. Wenn der Typ nicht direkt durch einen Platzhalter parametrisiert wird, muss der Typparameter genau übereinstimmen - List<Integer> und List<?> stimmen nicht genau überein. (Es ist ein Wildcard tief drin, aber es ist als Teil des konkreten Typs List<?>, kein Platzhalter auf der obersten Ebene.)

Um in der Lage zu sein, verschiedene Typparameter zu nehmen, muss es einen Platzhalter haben auf der obersten Ebene:

public void example4(List<? extends List<?>> listOfLists) {} 
1

Das funktioniert für mich:

List<List<Integer>> listOfLists1; 
List<List<?>> listOfLists2; 

public TestKlasse() { 
    init(); 
} 

public void init(){ 
    listOfLists1 = new ArrayList(); 
    listOfLists2 = new ArrayList(); 
    listOfLists1.add(Arrays.asList(1,2,3,4,5)); 
    listOfLists2.add(Arrays.asList("a","a",2,4,"5")); 
    test((Collection)listOfLists1); 
    test((Collection)listOfLists2); 
} 

private void test(Collection<Collection<?>> list){ 
    list.forEach(e -> { 
     System.out.println(e.toString()); 
    }); 
} 

Das Ergebnis:

[1, 2, 3, 4, 5] 
[a, a, 2, 4, 5] 

Ich hoffe, dass diese Lösung Ihre Erwartungen passen.