10

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>());

vpiTriumph
  • 3,116
  • 2
  • 27
  • 39

1 Answers1

15

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.

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • Question, is it possible to do `LinkedList> numList = new LinkedList>();` ? – user2336315 Nov 25 '13 at 22:44
  • Yes, that is possible. – rgettman Nov 25 '13 at 22:45
  • @SotiriosDelimanolis I'll see if I can find some supporting documentation. – rgettman Nov 25 '13 at 22:45
  • I actually experimented with this solution. From here, why doesn't: `numList.add(new LinkedList());` work? I get a `capture extends List extends Integer> cannot be applied to LinkedList`. – vpiTriumph Nov 25 '13 at 22:47
  • Have a look at my answer to http://stackoverflow.com/questions/20037561/assigning-a-generic-list-to-a-concrete-arraylist-is-causing-a-compile-time-error/ which is closely related; and at the many answers to http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicitly-p which is also related. – Dawood ibn Kareem Nov 25 '13 at 22:47
  • Related - [multiple nested wildcard - arguments not applicable](http://stackoverflow.com/questions/3652718/multiple-nested-wildcard-arguments-not-applicable) – rgettman Nov 25 '13 at 22:50
  • @rgettman -- Even after the proposed changes I'm still not quite able to achieve what I'm looking to do. Take a quick look at my comment? – vpiTriumph Nov 25 '13 at 22:58
  • Yeah, this solution won't let you add anything much to the list. You will find it hard to work with. My answer to the question that I linked to explains why. – Dawood ibn Kareem Nov 25 '13 at 23:06
  • 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`, 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> numList = new LinkedList>();`. You can add a `List` to such a `LinkedList`. – rgettman Nov 25 '13 at 23:10
  • @rgettman, your last comment hits the nail on the head. Update your actual answer with these details and I'll accept it. – vpiTriumph Nov 25 '13 at 23:31
  • Added the comment to my answer. – rgettman Nov 25 '13 at 23:34