开发者

Java generics and upcasting

Can somebody explain me why this

Map<String, List<String>> foo = new HashMap<String, LinkedList<String>>();

generates a type mismatch error ?

Type mismatch: cannot con开发者_StackOverflow社区vert from HashMap< String,LinkedList< String>> to Iterators.Map< String,List< String>>

Hashmap implements the Map interface, and LinkedList implements the List interface. Moreover, this

List<String> foo = new LinkedList<String>();

works...

Thanks


Because a Map<String, List<String>> allows you to put an ArrayList<String> into it, but doing so would violate the type integrity of a HashMap<String, LinkedList<String>>.

Either declare your HashMap as a HashMap<String, List<String>> or your variable as a Map<String, LinkedList<String>> or Map<String, ? extends List<String>>.

Edit

The more immediate problem is that you have imported the wrong Map class (something called Iterators.Map) or you have another class (or inner class rather) called Map in the same package as this code. You want to import java.util.Map.


In Java , Generics does not preserve subtype-covariance. So , if B is a subtype of A , Gen(B) may not be subtype of Gen(A) where Gen is some form of a Generic usage of a type.

Concretely , if LinkedList is a subtype of List , that does not imply that Map<String,LinkedList> is a subtype of Map<String,List>. As other posts have suggested , you have to use List as your type in the HashMap type parameters.


Fix this like the following:

Map<String, List<String>> result = new HashMap<String, List<String>>();

Pay attention that I changed LinkedList to List in the right side of your assignment.

You are right that LinkedList implements List. But I think that explanation of this error is not in definition of List but in definition of interface Map<K,V>.

The left side of your expression says that you want to create Map of String and List, i.e. V is "replaced" by List. Right side uses LinkedList. Although LinkedList implements List it does not work because the definition of Map is not something like Map<K, V extends List>, so compiler requires exact match.

I am not sure that my description is strict enough, but anyway this is the way to right generics. Really, when you create map of list you do not care about the implementation of List, therefore say HashMap<String, List<String>>. Only when you create instance of List care about its implementation. This will allow you to change the implementation if future without modification of other code.


Please use the Interface for the HashMap:

Map<String, List<String>> foo = new HashMap<String, List<String>>();

List<String> bar = new LinkedList<String>();

foo.put("barkey", bar);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜