The most specific type that this works for is ? extends List<? extends ?> ? extends List<? extends ?> ? extends List<? extends ?> :
class Testcase { public <E> List<List<E>> transform(List<List<E>> list) { return list; } public <E> List<List<? extends E>> transform2(List<List<? extends E>> list) { return list; } public <E> List<? extends List<? extends E>> transform3(List<? extends List<? extends E>> list) { return list; } public void test(String[] args) { List<List<Integer>> known = new ArrayList<>(); List<List<? extends Number>> unknown = new ArrayList<>(); transform(known);
Here is an explanation of why this makes sense.
A List<? extends Number> List<? extends Number> is obviously not a List<E> for any E , because it does not need to insert instances of the most common E , so the first determination is not performed.
A List<Integer> corresponds to List<? extends Number> List<? extends Number> , but this does not help, because these types are still unequal, so the types List<List<Integer>> and List<List<? extends Number>> List<List<? extends Number>> not fully connected. Therefore, the second definition also fails.
Instead, you should use the smallest top border of the site List<List<Integer>> and List<List<? extends Number>> List<List<? extends Number>> . You can get it using the following rule: LUB-site-use-site List<A> and List<B> :
USLUB(List<A>, List<B>) = List<? extends USLUB(A, B)>
Now, step by step:
- For
A = Integer and B = ? extends Number B = ? extends Number smallest upper bound ? extends Number ? extends Number because Integer matches ? extends Number ? extends Number . - For
List<Integer> and List<? extends Number> List<? extends Number> becomes the smallest upper bound ? extends List<? extends Number> ? extends List<? extends Number> - So the end result is
List<? extends List<? extends Number>> List<? extends List<? extends Number>> List<? extends List<? extends Number>> .
Hooray for dispersion using the site;)
source share