Reputation: 112
I am trying to write a method that takes any List of List as a parameter - regardless of the type of the nested list.
For a method that takes a single list of any type, the wildcard type works fine (see example1). But this concept does not extends to a list of lists. As can be see in example2 the method then only accepts parameters of type List<List<?>>
but not of a specific type such as List<List<Integer>>
. Example3 uses a type parameter T
and accepts List<List<Integer>>
but no longer accepts List<List<?>>
. Why is this and how can I write a method that accepts both List<List<?>>
and List<List<Integer>>
?
public void test()
{
List<Integer> list1;
List<?> list2;
example1(list1); // Valid
example1(list2); // Valid
List<List<Integer>> listOfLists1;
List<List<?>> listOfLists2;
example2(listOfLists1); // Error
example2(listOfLists2); // Valid
example3(listOfLists1); // Valid
example3(listOfLists2); // Error
}
public void example1(List<?> list) {}
public void example2(List<List<?>> listOfLists) {}
public <T> void example3(List<List<T>> listOfLists) {}
Upvotes: 2
Views: 317
Reputation: 122439
example2
doesn't work because List<List<Integer>>
is not a subtype of List<List<?>>
even though List<Integer>
is a subtype of List<?>
, similar to how List<String>
is not a subtype of List<Object>
even though String
is a subtype of Object
. Basically, when the type is not directly parameterized by a wildcard, the type parameter must match exactly -- List<Integer>
and List<?>
do not match exactly. (There is a wildcard deep inside there, but it is as part of the concrete type List<?>
, not a wildcard at the top level.)
For it to be able to take different type parameters, it needs to have a wildcard at the top level:
public void example4(List<? extends List<?>> listOfLists) {}
Upvotes: 4
Reputation: 71
That works for me:
List<List<Integer>> listOfLists1;
List<List<?>> listOfLists2;
public TestKlasse() {
init();
}
public void init(){
listOfLists1 = new ArrayList();
listOfLists2 = new ArrayList();
listOfLists1.add(Arrays.asList(1,2,3,4,5));
listOfLists2.add(Arrays.asList("a","a",2,4,"5"));
test((Collection)listOfLists1);
test((Collection)listOfLists2);
}
private void test(Collection<Collection<?>> list){
list.forEach(e -> {
System.out.println(e.toString());
});
}
The result:
[1, 2, 3, 4, 5]
[a, a, 2, 4, 5]
I hope that this solution fit your expectation.
Upvotes: 1