You should declare your method as:
private void bar(final List<? extends List<?>> lists) {...}
In this case the call bar(new ArrayList<List<String>>());
would work.
The explanation
In short:
List<SomeType>
- The compiler will expect a call with exactly the same type.
List<? extends SomeType>
- The compiler will expect a call with a class that is a compatible (sublass) with SomeType
.
In your case a definition
void bar (final List<List<?>> list)
will expect a parameter whose definition is exactly List<List<?>>() nestedList;
On the other hand, when you specify your method as:
void bar(final List<? extends List<?>> lists)
Then you're saying that you have a list whose types are upper-bounded by List<?>
, so ArrayList<String>
would be a valid candidate for the nested list
From Oracle docs:
There is a small but very important difference here: we have replaced
the type List with List. Now drawAll() will
accept lists of any subclass of Shape, so we can now call it on a
List if we want.
List is an example of a bounded wildcard. The ?
stands for an unknown type, just like the wildcards we saw earlier.
However, in this case, we know that this unknown type is in fact a
subtype of Shape. (Note: It could be Shape itself, or some subclass;
it need not literally extend Shape.) We say that Shape is the upper
bound of the wildcard.