I have a function
public static void bar (final List<List<?>> list)
{
}
which I can call with a wildcard (<?>
)
bar(new ArrayList<List<?>>());
but not with another type (e.g. String
)
// The method bar(List<List<?>>) in the type Foo is not
// applicable for the arguments (ArrayList<List<String>>)
bar(new ArrayList<List<String>>());
However this works for the similar function
public static void foo(List<?> l)
{
}
public static void main(String[] args)
{
// no error
foo(new ArrayList<String>());
}
Can you please explain, why the compiler complains in the first case but not in the second?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With