2009-05-16 21 views
6

Esiste un modo per rendere la seguente implementazione in un modo sicuro?Java Generics che inserisce sulla mappa <String,? estende la lista <String>>

public void myMethod(Map<String, ? extends List<String>> map) 
{ 
    map.put("foo", Collections.singletonList("bar"); 
} 

L'implementazione di cui sopra non funziona. È necessario un Map<String, ? super List<String>> per compilare correttamente il metodo map.put(). Ma myMethod non accetterà alcun sottotipo di List in questo modo. Quindi, devo usare Map<String, ? extends List<String>> invece. Come posso risolvere questo problema in un modo sicuro?

risposta

20
public void myMethod(Map<String, List<String>> map) { 
    map.put("foo", Collections.singletonList("bar")); 
} 

Non si può mettere un (il tipo List ritorno di Collections.singletonList() in un Map di ? extends List dal momento che il tipo effettivo potrebbe essere una qualsiasi implementazione di List. Ad esempio, è non sicuro di mettere un generico List in un Map<String,LinkedList> dal momento che il List potrebbe non essere una LinkedList. Tuttavia, possiamo facilmente mettere un LinkedList in un Map di <String,List>.

penso che tu w Prima di pensare ai tuoi generici. Non è necessario utilizzare ? extends per una classe non generica. Ad esempio, List<Object> manterrà qualsiasi Object, il numero ? extends non è necessario per aggiungere un oggetto. A List<List<Foo>> sono necessari solo gli oggetti List<Foo> e non gli oggetti List<FooSubclass> [Le classi generiche non ereditano in base ai relativi parametri]. È qui che entra in gioco ? extends. Per aggiungere sia List<Foo> e List<FooSubclass> a List, il tipo deve essere List<List<? extends Foo>>.

+2

+1 per una buona spiegazione (ora che i tuoi generici sono visibili: P). –

+0

Oops. Continuo a pensare che, dal momento che i filtri SOF scrivono comunque che aggiusta la staffa angolata. Oh bene... – KitsuneYMG

6

Map<String, List<String> non funziona? C'è qualche ragione particolare per cui devi avere un jolly?

0

Immagina se qualcuno ti ha passato un Map<String, ArrayList<String>>. Il valore che stai inserendo è il risultato di Collections.singletonList che è non e ArrayList.

Non è possibile accettare alcun sottotipo di Elenco nella mappa e quindi aspettarsi di poter aggiungere il proprio sottotipo, eventualmente incompatibile.

4

C'è un principio molto semplice quando si usano Collezioni e Generici insieme. Si chiama "The Get and The Principle":

Utilizzare un carattere jolly "extends" quando si estrae solo i valori da una raccolta, utilizzare il carattere jolly "super" quando si inseriscono solo valori in una raccolta e non si utilizzano qualsiasi carattere jolly quando si desidera sia get and put.

Quindi, come potete vedere, l'esempio iniziale non è valido, secondo questo principio.

Problemi correlati