Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested Bounded Wildcard

When I try to compile the following code:

LinkedList<List<? extends Number>> numList = new LinkedList<List<Integer>>();

I get an incompatible type error:

Required: LinkedList <java.util.list<? extends java.lang.Number>>
Found: LinkedList <java.util.list<Integer>>

How can I achieve having a LinkedList which contains elements that are Lists with elements that extend Number?

To be clear, I'm looking to add lists to numList in the following fashion:

numList.add(new LinkedList<Integer>());

like image 983
vpiTriumph Avatar asked Nov 25 '13 22:11

vpiTriumph


1 Answers

Wildcard capture does not go more than one generic level deep. So while this works:

LinkedList<? extends Number> test = new LinkedList<Integer>();

This does not:

LinkedList<List<? extends Number>> numList = new LinkedList<List<Integer>>();

The most reasonable explanation I can think of is to think of generics as invariant at the outermost level. A LinkedList<List<Integer>> is not a LinkedList<List<? extends Number>>, even though a List<Integer> is a List<? extends Number>, for the same reason that a List<Dog> is not a List<Animal> even though a Dog is an Animal. Here, Dog is to Animal as List<Integer> is to List<? extends Number>.

Well, the Dog/Animal solution is ? extends:

List<? extends Animal> animals = new List<Dog>();

Applying the same reasoning, the workaround is another ? extends:

LinkedList<? extends List<? extends Number>> numList = new LinkedList<List<Integer>>();

However, you won't be able to add anything to this list because of the first ? extends. The reference type variable numList doesn't know which subtype of List<? extends Number> it really is; it could be ArrayList<Integer>, so Java cannot provide the type safety that such a thing can be added to such a LinkedList. To maintain type safety, the compiler will only allow adding null. You'll have to match the generic type parameters exactly, with no wildcards: LinkedList<List<Integer>> numList = new LinkedList<List<Integer>>();. You can add a List<Integer> to such a LinkedList.

like image 138
rgettman Avatar answered Oct 18 '22 05:10

rgettman