- A
List
whose elements are lists of dogs
- A
List
whose elements are lists of a type that extends Dog
- A
List
whose elements are a single subtype of a list of dogs
- A
List
whose elements are a single subtype of a (list of a type that extends Dog
)
- A
List
whose elements are a single supertype of a (list of a type that extends Dog
)
- A
List
whose elements are a single subtype of a (list of a type that super Dog
)
Where "subtype", "supertype", "super", and "extends" are the "generic" versions (i.e. also includes the bounding type)
Examples with Number
and subtypes, because why not. Replace Dog
with Number
.
List<List<Number>>
might look like a 2D array of Number
elements. Pretty simple.
List<List<? extends Number>>
might look like a 2D array, where each row is a different subtype of number. For example, the first row might be a List<Integer>
, the second row might be a List<Double>
, etc.
List<? extends List<Number>>
might be a List<ArrayList<Number>>
, List<List<Number>>
, List<LinkedList<Number>>
, etc. The Number
has to stay, because generics are invariant, but you can have List
or any of its subtypes as the "overall" type of the elements. You can only pick one of List
or its subtypes though, and the one you pick you have to stay with.
List<? extends List<? extends Number>>
is similar to List<? extends List<Number>>
, except now you can pick Number
or any of its subclasses as the elements of the "overall" 2D array. So you can have List<List<Integer>>
, List<ArrayList<Integer>>
, List<LinkedList<Double>>
, etc. As before, you can only pick one of List
's subtypes and one of Number
's subtypes.
- (tricky!)
List<? super List<? extends Number>>
appears to be equivalent to List<List<? extends Number>>
, List<Collection<? extends Number>>
, etc. but not List<List<Number>>
or anything concrete where a subtype of Number
is used. I think this is because List<Number>
isn't considered a supertype of List<? extends Number>
, which I suppose makes sense due to generics being invariant. List<Object>
as well as raw types (List<List>
, List<Collection>
, etc.) also works.
- Same thing as 4, except you get either
List<Number>
or List<Object>
(and apparently List<Serializable>
) as the inner list.
As @MadProgrammer said, due to PECS (Producer-Extends-Consumer-Super), any time you have a ? extends
for your generic type you won't be able to update the list, only retrieve items from it. So no add()
-ing and no set()
-ing.