While working on interview questions, I have come across below code:
List<Object> list = new ArrayList();
Map<Object, ? super ArrayList> m = new HashMap<Object, ArrayList>();
m.put(1, new Object());
m.put(2, list);
The above two put method's are throwing compile time error. But, when I add m.put(3, new ArrayList());
it is adding to map with no compile time error.
It is very clear for me that I can add new Object()
as a value in HashMap
because of the map declaration to be of type < ? super ArrayList>
; it means I can add any value that is higher than ArrayList
(i.e. super of ArrayList
) and ArrayList
object too, but not anything below ArrayList
.
This particular concept is very well written in SCJP 6 by Kathy Sierra and Bert Bates and based on that theory and examples I assumed it should do job as I understood. Can someone help me understand the error?
A HashMap contains key-value pairs, there are three ways to convert a HashMap to an ArrayList: Converting the HashMap keys into an ArrayList. Converting the HashMap values into an ArrayList. Converting the HashMap key-value pairs into an ArrayList.
The term generic simply is the idea of allowing the type (Integer, Double, String, etc. or any user-defined type) to be the parameter to methods, class, or interface. For eg, all the inbuilt collections in java like ArrayList, HashSet, HashMap, etc. use generics.
Both are better based on your requirements, if you need to store a set of similar objects in a list like data structure then ArrayList is better and if you want to store key and value pair HashMap is better.
The type ? super ArrayList
means an unknown type, which has a lower bound of ArrayList
. For example, it could be Object
, but might be AbstractList
or ArrayList
.
The only thing the compiler can know for sure is that the type of the value, although unknown, is guaranteed to be no more specific than ArrayList
, so any object that is an ArrayList
, or a subclass of ArrayList
, may be added.
Also remember: the compiler only goes by the declared type; it ignores the assigned type.
put(1, new Object())
fails:Clearly, Object
is not within bounds.
put(1, list)
fails:The variable is of type List
, which may hold a reference to a LinkedList
, which is not within the required bounds.
You are misunderstanding what the wildcard ?
means. You probably have a common misconception:
It does not mean that you can put any kind of object in the map which is of a type that is a superclass of ArrayList
.
What it means is that the values in the map are of some unknown type that is a supertype of ArrayList
. Since the exact type is not known, the compiler won't allow you to put a value of any type other than ArrayList
itself as a value in the map - the compiler does not have enough information to check if what you are doing is type-safe.
Suppose that this was allowed, then you could do bad things like this:
Map<Object, ArrayList> m1 = new HashMap<Object, ArrayList>();
Map<Object, ? super ArrayList> m2 = m1;
// This should not be allowed, because m2 is really a HashMap<Object, ArrayList>
m2.put(1, new Object());
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