2013-02-13 9 views
6

Ho una domanda su questo metodo da java.util.Collections:Generics Collezioni 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)); 
    } 
} 

Capisco come <? super T> lavori, tuttavia, non capisco il motivo per cui il primo parametro è List<? super T> invece di List<T>. Penso che sia inutile in questa situazione.
Utilizzare List<T> dovrebbe funzionare anche, non dovrebbe?
Potresti fornirmi qualche esempio per capirlo, se possibile, per favore?

Grazie.

risposta

5

No, ha senso. Ad esempio, si consideri questa situazione:

  • T è InputStream
  • dest è un List<Object>
  • src è un List<FileInputStream>

che funziona assolutamente bene. Naturalmente, si potrebbe fare T sia Object o FileInputStream in questa situazione - ma immaginate voi stessi chiamando questo da un metodo con una firma di:

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

Tu non sai che è un List<InputStream> - solo che è un List<? super InputStream>. Se il parametro in copy fosse soloList<T>, saremmo bloccati ... ma con il modo in cui è è scritto, stiamo bene.

Ha anche senso in termini di ciò che abbiamo bisogno dalla lista di destinazione - noi solo dobbiamo essere in grado di impostare i valori di T al suo interno. Allo stesso modo tutto ciò che chiediamo dall'elenco sorgente è che possiamo ottenere i valori di T da esso. <? super T> e <? extends T> esprimono bene tali requisiti.

+0

OK, ottima spiegazione !. Molte grazie. –

0

Se si analizza il motivo per cui viene utilizzato List, sarà un po 'più chiaro.

Quando un metodo intende popolare un elenco, è possibile limitarlo per utilizzare un tipo specifico T, tuttavia spesso si potrebbe voler essere meno restrittivo.

Per esempio, supponiamo di avere un metodo populateWithStudents(List<Student> list) E avete Student extend Person

Questo significa che non è possibile utilizzare questo metodo con un List<Person> per riempirlo con oggetti Student, anche se Studente extends Persona.

Quindi, se invece vogliamo consentire che lo cambiamo a populateWithStudents(List<? super Student> list). In questo modo stiamo dicendo che finché possiamo inserire uno Studente nell'elenco, indipendentemente dal fatto che si tratti di un elenco di oggetti Studente o di una qualsiasi delle sue superclassi, è permesso.

Questo non è solo quando si popola ovviamente, ma questo esempio aiuta a comprendere il concetto.