通配符捕获java方法参数和参数类型

时间:2018-04-10 12:06:25

标签: java generics wildcard

我正在阅读Maurice Naftalin的书Java generics and collections

在关于通配符捕获的部分中,作者举了一个例子

public static void reverse(List<?> list) { 
    rev(list); 
}

private static <T> void rev(List<T> list) {
    List<T> tmp = new ArrayList<T>(list);
    for (int i = 0; i < list.size(); i++) {
        list.set(i, tmp.get(list.size()-i-1));
    }
}

但我认为类型List<T>List<?>的子类型(其中List<?>List<? extends Object>的简写语法)(我对List<T>的假设是List<? extends Object>的子类型甚至是正确的吗?),因此在reverse方法中,我们如何将变量listList<? extends Object>}类型传递给rev方法, rev方法参数的类型为List<T>

3 个答案:

答案 0 :(得分:3)

  

我们如何将变量列表(类型List<? extends Object>)传递给rev方法

你不是。

每个列表都有一个类型:您无法创建new ArrayList<?>new ArrayList<? extends String>。您可以创建new ArrayList<String>,并将其分配给具有通配符类型的变量。

所以,你可以调用一个方法List<T>,即使有List<?>作为参数,只要编译器可以推断出某些类型与界限。你不知道类型,但编译器可以。

答案 1 :(得分:2)

  

但我认为类型List<T>List<?>

的子类型

事实并非如此:请记住,Java中的泛型是不变的。这意味着即使X是Y的子类型,List<X>也不会是List<Y>的子类型。

代码示例的工作原因是reverse方法匹配任何List类型,甚至是原始类型。

答案 2 :(得分:2)

在此声明中:

private static <T> void rev(List<T> list) {...}

T是一种方法参数化类型,没有显式绑定引用任何类型。

您可以在方法中传递一个声明为List<? extends Object>List<?>甚至List<String>的变量,因为它接受List中的任何类型。