0

I want to implement a map wrapper that use genericity to enforce a type relation between the key and the value. The following code does not compile :

Map<Class<? extends Serializable>, List<List<? extends Serializable>>> collection = new HashMap();

private <T extends Serializable> void add(Class<T> type, List<List<T>> item) {
    collection.put(type, item);
}

whereas this compile :

Map<Class<? extends Serializable>, List<? extends Serializable>> collection = new HashMap();

private <T extends Serializable> void add(Class<T> type, List<T> item) {
    collection.put(type, item);
}

why is there a difference between a 2nd and a 3rd level generic type ?

Steve Marion
  • 289
  • 1
  • 9

1 Answers1

2

Generics are invariant, the second type parameter of your map is List<List<? extends Serializable>>, that means that the second argument of put must match this exactly.

i.e. You can only add a List to the map if it has the exact parameter List<? extends Serializable>, and T is not exactly ? extends Serializable.

You can fix this by having another ? extends in your map and method declaration:

Map<Class<? extends Serializable>, List<? extends List<? extends Serializable>>> collection = new HashMap<>();

private <T extends Serializable> void add(Class<T> type, List<? extends List<T>> item) {
    collection.put(type, item);
}
Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93