Problem with map declaration <String, Class <? Extends Serializable >>
Java provides me with <? extends class> <? extends class> way to filter java classes that you can use to build a new HashMap in this case, for example:
I can do it:
Map<String,? extends Serializable> map1 = new HashMap<String,String>(); This is correct because String implements Serializable, so the compiler allows me to do this.
But when I try to do this:
Map<String,GenericClass<? extends Serializable>> map2 = new HashMap<String, GenericClass<String>>(); Being a GenericClass like this:
public class GenericClass<T> { . . . } The compiler gives an error message:
Type mismatch: cannot convert from HashMap<String,GenericClass<String>> to Map<String,GenericClass<? extends Serializable>> I would like to know what is going on?
Perhaps the compiler cannot detect that the extends class is part of a generic type.
You will need to use the following:
Map<String, ? extends GenericClass<? extends Serializable>> map2 = new HashMap<String, GenericClass<String>>(); Nested wildcards are very different from top-level wildcards — only the last ones perform group capture . As a result, HashMap<String, GenericClass<String>> is considered irreversible for Map<String, GenericClass<? extends Serializable>> Map<String, GenericClass<? extends Serializable>> because GenericClass<? extends Serializable> GenericClass<? extends Serializable> is an argument of a specific type (and because generics are not covariant ).
See this post for more information on nested wildcards: Multiple wildcards for common methods make the Java compiler (and me!) Very confusing
Map<String,? extends Serializable> map1 = new HashMap<String,String>(); map1 contains an unlimited V , which requires only an unknown Serializable value. Therefore, it cannot find the generic object associated with this except null .
Map<String,GenericClass<? extends Serializable>> map2 = new HashMap<String, GenericClass<String>>(); map2 limited by type K (in this case String ) and V ( Class<? exends Serializable ). This is how the Java compiler sees boundaries.
Essentially, you cannot put anything in map1 other than zero, since you will only see map1.put(String key, null value) //Compiler is asking WTF here . Whereas map2 will essentially "map" as map2.put(String key, Class<? extends Serializable> value); //Much better... map2.put(String key, Class<? extends Serializable> value); //Much better...
Due to the restriction of V in map2 signature must be the same in its declaration.