Java嵌套泛型类型不匹配

时间:2012-11-05 10:15:34

标签: java generics java-6 nested-generics

在以下示例中:

public static void main(String[] args) {

    List<String> b = new ArrayList<String>();
    first(b);
    second(b);

    List<List<String>> a = new ArrayList<List<String>>();
    third(a);
    fourth(a);  // doesnt work

}

private static <T> void first(List<T> a){
    System.out.println("List of T");
}

private static void second(List<?> a){
    System.out.println("List of anything ");
}

private static <T> void third(List<List<T>> a){
    System.out.println("List of a List of T ");
}

private static void fourth(List<List<?>> a){
    System.out.println("List of a List of anything ");
}

为什么第二个(b)的呼叫有效,但第四个(a)的呼叫不

我收到以下错误:

The method fourth(List<List<?>>) in the type `TestTest` is not applicable for the arguments (`List<List<String>>`)

5 个答案:

答案 0 :(得分:14)

如果您希望能够使用fourth参数调用List<List<String>>,那么您需要将签名更改为:

private static void fourth(List<? extends List<?>> a){
    System.out.println("List of a List of anything ");
}

上述方法有效,因为与List<List<?>>不同,List<? extends List<?>>List<List<String>>兼容。想一想:

List<List<String>> original = null;
List<? extends List<?>> ok  = original; // This works
List<?> ok2                 = original; // So does this
List<List<?>> notOk         = original; // This doesn't

List<Integer> original      = null;
List<? extends Number> ok   = original; // This works
List<?> ok2                 = original; // So does this
List<Number> notOk          = original; // This doesn't

推理很简单。如果你有

private static void fourth(List<List<?>> a) {
    List<?> ohOh = Arrays.asList(new Object());
    a.add(ohOh);
}

然后,如果你可以调用该方法:

List<List<String>> a = new ArrayList<List<String>>();
fourth(a);
String fail = a.get(0).get(0); // ClassCastException here!

答案 1 :(得分:5)

List<List<String>>不是List<List<?>>

无论List<?>是什么,您都应该能够将List<List<?>>放入?List<List<String>>只接受List<String>

答案 2 :(得分:2)

  

这意味着类型是未知的,任何类型的对象都可以添加到List<List<?>> heterogeneous,并且编译器不能保证List<List<?>>中的所有对象都是相同的类型。因此,它无法传递给以有界类型为参数的新ArrayList<List<String>>()

答案 3 :(得分:1)

List<List<String>>List<List<?>>不同。泛型在本质上是不变的。如果您只执行List<?>并通过List<String>,那么它将起作用,因为List of Anything可以由Lists of String表示。

List of List of anything无法代表List of List of String

@Lukas Elder已经指定了可行的案例。这是第二个可行的案例

private static void fourth(List<?> a){
    System.out.println("List of anything ");
}

答案 4 :(得分:0)

List<List<?>> == List {                 //That contains any unknown type lists
                        List<Integer>,
                        List<String>,
                        List<Object>
                      }

在哪里

List<? extends List<?> == List {       //That contains same unknown type lists
                        List<Integer>,
                        List<Integer>,
                        List<Integer>
                      }

所以这里

 List<List<String>> == List {        //That contains same String lists
                        List<String>,
                        List<String>,
                        List<String>
                      }

因此List<? extends List<?>List<List<String>>的超级类型且可分配。

调用fourth方法的有效值如下所示。

    List<List<?>> a1 =  new ArrayList<List<?>>();
    a1.add(new ArrayList<String>());
    a1.add(new ArrayList<Integer>());
    a1.add(new ArrayList<Object>());