嵌套列表中的通用类型和通配符
Generic types and wildcards in nested lists
我正在尝试编写一个方法,将任何列表的列表作为参数 - 无论嵌套列表的类型如何。
对于采用任何类型的单个列表的方法,通配符类型工作正常(参见示例 1)。但是这个概念并没有扩展到列表的列表。从示例 2 中可以看出,该方法仅接受 List<List<?>>
类型的参数,但不接受 List<List<Integer>>
等特定类型的参数。示例 3 使用类型参数 T
并接受 List<List<Integer>>
但不再接受 List<List<?>>
。为什么会这样,我如何编写一个同时接受 List<List<?>>
和 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) {}
对我有用:
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());
});
}
结果:
[1, 2, 3, 4, 5]
[a, a, 2, 4, 5]
希望这个解决方案符合您的期望。
example2
不起作用,因为 List<List<Integer>>
不是 List<List<?>>
的子类型,即使 List<Integer>
是 List<?>
的子类型,类似于List<String>
不是 List<Object>
的子类型,尽管 String
是 Object
的子类型。基本上,当类型没有被通配符直接参数化时,类型参数必须完全匹配——List<Integer>
和 List<?>
不完全匹配。 (里面有一个通配符,但它是具体类型的一部分List<?>
,而不是顶层的通配符。)
为了能够接受不同类型的参数,它需要在顶层有一个通配符:
public void example4(List<? extends List<?>> listOfLists) {}
我正在尝试编写一个方法,将任何列表的列表作为参数 - 无论嵌套列表的类型如何。
对于采用任何类型的单个列表的方法,通配符类型工作正常(参见示例 1)。但是这个概念并没有扩展到列表的列表。从示例 2 中可以看出,该方法仅接受 List<List<?>>
类型的参数,但不接受 List<List<Integer>>
等特定类型的参数。示例 3 使用类型参数 T
并接受 List<List<Integer>>
但不再接受 List<List<?>>
。为什么会这样,我如何编写一个同时接受 List<List<?>>
和 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) {}
对我有用:
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());
});
}
结果:
[1, 2, 3, 4, 5]
[a, a, 2, 4, 5]
希望这个解决方案符合您的期望。
example2
不起作用,因为 List<List<Integer>>
不是 List<List<?>>
的子类型,即使 List<Integer>
是 List<?>
的子类型,类似于List<String>
不是 List<Object>
的子类型,尽管 String
是 Object
的子类型。基本上,当类型没有被通配符直接参数化时,类型参数必须完全匹配——List<Integer>
和 List<?>
不完全匹配。 (里面有一个通配符,但它是具体类型的一部分List<?>
,而不是顶层的通配符。)
为了能够接受不同类型的参数,它需要在顶层有一个通配符:
public void example4(List<? extends List<?>> listOfLists) {}