2013-02-13 8 views
6

Ich habe eine Frage zu diesem Verfahren von java.util.Collections:Generics Kollektionen PECS

public class Collections { 
    public static <T> void copy(List<? super T> dest, List<? extends T> src) { 
     for (int i=0; i<src.size();i++) 
     dest.set(i,src.get(i)); 
    } 
} 

Ich verstehe, wie <? super T> funktioniert, aber ich verstehe nicht, warum der erste Parameter List<? super T> statt List<T> ist. Ich denke, es ist in dieser Situation nutzlos.
Die Verwendung von List<T> sollte auch funktionieren, sollte es nicht?
Können Sie mir bitte einige Beispiele geben, um es zu verstehen, wenn möglich, bitte?

Danke.

Antwort

5

Nein, es macht Sinn. Betrachten wir zum Beispiel diese Situation:

  • T ist InputStream
  • dest ein List<Object>
  • src ist ein List<FileInputStream>

ist die absolut gut funktioniert. Natürlich könnte SieT entweder Object oder FileInputStream in dieser Situation machen - aber stellen Sie sich mit einer Signatur einer Methode dieses von riefen:

public void doSomething(List<? super InputStream> streams) { 
    // I want to use copy in here for some reason 
} 

wissen Sie nicht, dass es ein List<InputStream> ist - nur das ist ein List<? super InputStream>. Wenn der dest Parameter in copy wäre nurList<T>, würden wir feststecken ... aber mit der Art, wie es geschrieben ist, geht es uns gut.

Es macht auch Sinn in Bezug auf was wir von der Zielliste benötigen - wir nur müssen in der Lage sein, Werte von T darin zu setzen. Ebenso benötigen wir für die Quellenliste nur, dass wir Werte von T daraus erhalten können. <? super T> und <? extends T> drücken diese Anforderungen gut aus.

+0

OK, großartige Erklärung !. Danke vielmals. –

0

Wenn Sie brechen sie in warum die Liste verwendet wird, es wird ein bisschen mehr klar sein.

Wenn eine Methode eine Liste füllen will, könnte man es einschränken einen bestimmten Typ T verwenden, aber oft wollen Sie vielleicht weniger restriktiv.

Zum Beispiel können Sie sagen haben eine Methode populateWithStudents(List<Student> list) Und Sie haben Student extend Person

Das bedeutet, dass Sie nicht diese Methode mit einem List<Person> verwenden können Objekte mit Studenten zu füllen, auch wenn Student erstreckt.

Also, wenn auf der anderen Seite möchten wir erlauben, dass wir es zu populateWithStudents(List<? super Student> list) ändern. Auf diese Weise sagen wir, dass es erlaubt ist, einen Schüler in die Liste aufzunehmen, egal ob es sich um eine Liste von Schüler-Objekten oder um eine Liste von Superklassen handelt.

Dies ist nicht nur, wenn offensichtlich bevölkern, aber dieses Beispiel hilft, das Konzept zu verstehen.