Nested Bounded Wildcard
Asked Answered
E

1

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

Exorbitant answered 25/11, 2013 at 22:40 Comment(0)
S
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.

Severalty answered 25/11, 2013 at 22:42 Comment(11)
Question, is it possible to do LinkedList<List<Number>> numList = new LinkedList<List<Number>>(); ?Alloy
Yes, that is possible.Severalty
@SotiriosDelimanolis I'll see if I can find some supporting documentation.Severalty
I actually experimented with this solution. From here, why doesn't: numList.add(new LinkedList<Integer>()); work? I get a capture<? extends List<? extends Integer> cannot be applied to LinkedList<Integer>.Exorbitant
Have a look at my answer to #20038061 which is closely related; and at the many answers to #2745765 which is also related.Juliennejuliet
Related - multiple nested wildcard - arguments not applicableSeveralty
@Severalty -- 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?Exorbitant
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.Juliennejuliet
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.Severalty
@rgettman, your last comment hits the nail on the head. Update your actual answer with these details and I'll accept it.Exorbitant
Added the comment to my answer.Severalty

© 2022 - 2024 — McMap. All rights reserved.