Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collection object creation using Generics

When I try to create object as below :

Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();

What is wrong syntactically, can any one explain me?

like image 385
Tushar Trivedi Avatar asked Apr 12 '13 09:04

Tushar Trivedi


2 Answers

Generics are not co-variant. You can use:

Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, Map<String, Integer>>();
^                                                                ^
--------------^------------------- becomes ------^               |
              -----------------must remain as type ---------------

While the Map on the outer left hand side of the assignment can "become" a HashMap as assigned, the same cannot be applied to any types that appear as generic parameters.

Edit:

As noted by @Keppil, you can use the bounded wildcard syntax:

Map<Integer, ? extends Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();

Note that this syntax will not allow entries to be added to the map but is useful as a type to be passed to and from methods.

Some references:

  • Covariance
  • Generics Gotchas
  • Wildcards
like image 139
Reimeus Avatar answered Oct 08 '22 19:10

Reimeus


It is similar error like

List<Animal> list = new ArrayList<Dog>();

Parameterized type should be of same type at both end. There is no inheritance (IS-A) concept. If you still want to use it then use wildcard(?) with extend/super keyword which is allowed only at left side of the equals sign.

List<Animal> list = new ArrayList<Dog>(); // is not allowed

but

Animal[] animal = new Dog[10];  //is allowed
animal[0] = new Dog(); // is allowed

where it will later fail and throw exception if somebody tries to add Cat (extends Animal) object.

animal[1] = new Cat();  //compiles fine but throws java.lang.ArrayStoreException at Runtime.

Remember animal[1] or animal[index] is holding reference of Dog. So Dog reference variable can refer to Dog object not Cat object.

So to avoid such scenario, JSL have made such changes in generics list/Collection. This answer is also applicable for your question(Map).
Parameterized type should be of same type at both end.

List<Animal> list = new ArrayList<Animal>(); 
like image 34
AmitG Avatar answered Oct 08 '22 18:10

AmitG