The following compiles as expected:
List<Set<? extends Set<?>>> list = new ArrayList<Set<? extends Set<?>>>();
list.add(new HashSet<Set<String>>());
list.add(new HashSet<Set<Integer>>());
The problem is that generics is type invariant.
Consider the simpler example:
- Given that there is a casting conversion from
Animal to Dog (e.g. Dog extends Animal)...
- A
List<Animal> IS NOT a List<Dog>
- There is a capture conversion from
List<? extends Animal> to a List<Dog>
Now here's what happens in this scenario:
- Given that there is a capture conversion from
Set<?> to Set<String>...
- A
Set<Set<?>> IS NOT a Set<Set<String>>
- There is a capture conversion from
Set<? extends Set<?>> to Set<Set<String>>
So if you want a List<T> where you can add a Set<Set<String>>, Set<Set<Integer>>, etc, then T is NOT Set<Set<?>>, but rather Set<? extends Set<?>>.
Related questions
- Can't cast to to unspecific nested type with generics
- Multiple wildcards on a generic methods makes Java compiler (and me!) very confused
- Java Generic List<List<? extends Number>>
- Any simple way to explain why I cannot do List<Animal> animals = new ArrayList<Dog>()?
- What is the difference between <E extends Number> and <Number>?
See also
- Java Generics Tutorial
- Generics and Subtyping | Wildcards | More Fun with Wildcards
- Angelika Langer's Java Generics FAQ
- What is a bounded wildcard?
- Which super-subtype relationships exist among instantiations of generic types?