Consider my custom extended hashmap:
public class CustomHashMap extends HashMap<String, Object> {
...
}
Why doesn't this work since CustomHashMap is child of HashMap?
Map<String, HashMap<String, Object>> customs = new LinkedHashMap<String, CustomHashMap>();
But this works:
Map<String, HashMap<String, Object>> customs = new LinkedHashMap();
And also it works when adding (put) an CustomHashMap into the customs
Map.
customs.put("test", new CustomHashMap());
It seems weird that not specifying the generics at initialization works, but it doesn't otherwise.
You can't inherit from a Generic type argument. C# is strictly typed language. All types and inheritance hierarchy must be known at compile time. . Net generics are way different from C++ templates.
Generics also provide type safety (ensuring that an operation is being performed on the right type of data before executing that operation). Hierarchical classifications are allowed by Inheritance. Superclass is a class that is inherited. The subclass is a class that does inherit.
Yes you can do it.
Almost all reference types can be generic. This includes classes, interfaces, nested (static) classes, nested interfaces, inner (non-static) classes, and local classes. The following types cannot be generic: Anonymous inner classes .
This statement is not working
Map<String, HashMap<String, Object>> customs = new LinkedHashMap<String, CustomHashMap>();
because customs
is of type Map<String, HashMap<String, Object>>
and you are assigning a LinkedHashMap
which is of type <String, CustomHashMap>
, where CustomHashMap
is a sub class of HashMap<String, Object>
.
Generics are invariant
: for any two distinct types T1
and T2
, HashMap<String, T1>
is neither a subtype nor a supertype of HashMap<String, T2>
. So, LinkedHashMap<String, CustomHashMap>
cannot be assigned to Map<String, HashMap<String, Object>>
. On the other hand, arrays are covariant
, which means below statement will compile without any error or warning. But, it might fail at run time (which might cause more harm) if you put any other subtype of HashMap<String, Object>
into it other than CustomHashMap
:
HashMap<String, Object>[] mapArray = new CustomHashMap[1];
mapArray[0] = new CustomHashMap_1();// this will throw java.lang.ArrayStoreException
Now, if you want to assign LinkedHashMap<String, CustomHashMap>
to Map<String, HashMap<String, Object>>
, change the statement to this:
Map<String, ? extends HashMap<String, Object>> customs = new LinkedHashMap<String, CustomHashMap>();
Some additional information about this approach is nicely explained by @Seelenvirtuose , which is the accepted answer.
When working with generics, you should always keep type erasure in mind. At runtime an objct of type Map
does not know its type parameters anymore. The consequence: A LinkedHashMap<String, CustomHashMap>
is not a sub-type of Map<String, HashMap<String, Object>>
.
If you want to have somthing sub-type related you must do it the following way:
Map<String, ? extends HashMap<String, Object>> customs = new LinkedHashMap<String, CustomHashMap>();
This is called an upper-bounded wildcard and exists exactly for that case: To get a sub-type relationship. Please refer to the Java tutorial about generics for more information.
An additional info as per the comment:
The upper-bounded version has a disadvantage on how to use the customs map. You cannot put instances anymore into that map. The only value allowed is null
. The reason is, that you could have another class extending Map<String, HashMap>
and try to put an instance of that into your customs map. But this is a problem, as the variable customs refers to a map that was parameterized with CustomHashMap
.
When working with bounded wildcards, you should always remind PECS. PECS stands for "producer extends, consumer super". This is valuable for method parameters. If you write a method that only needs to read values from such a map, you could type the parameter as Map<String, ? extends Map<String, Object>>
. This is called a producer. If you only need to write to that map, use the keyword super. If you need both - read and write - you cannot do either.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With