简体   繁体   English

Java嵌套泛型类型不匹配

[英]Java nested generic type mismatch

In the following example: 在以下示例中:

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 ");
}

Why does the call to second(b) work, but the call to fourth(a) doesn't ? 为什么第二个(b)的呼叫有效,但第四个(a)的呼叫不起作用

I get the following error: 我收到以下错误:

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

If you want to be able to call fourth with a List<List<String>> argument, then you'll need to change your signature to this: 如果您希望能够使用List<List<String>>参数调用fourth ,那么您需要将签名更改为:

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

The above will work because unlike List<List<?>> , List<? extends List<?>> 以上将有效,因为不像List<List<?>>List<? extends List<?>> List<? extends List<?>> is compatible with List<List<String>> . List<? extends List<?>>List<List<String>>兼容。 Think of it this way: 想一想:

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

The reasoning is simple. 推理很简单。 If you had 如果你有

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

And then if you could call that method as such: 然后,如果您可以这样调用该方法:

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

A List<List<String>> isn't a List<List<?>> . List<List<String>>不是List<List<?>>

You should be able to put any List<?> into a List<List<?>> , no matter what the ? 您应该能够将任何List<?>放入List<List<?>> ,无论是什么? . A List<List<String>> will only accept a List<String> . List<List<String>>只接受List<String>

This implies that the type is unknown and objects of any type can be added to List<List<?>> that are heterogeneous and compiler cannot guarantee that all object in List<List<?>> are of same type. 这意味着类型是未知的,任何类型的对象都可以添加到heterogeneous List<List<?>> ,编译器不能保证List<List<?>>中的所有对象都是相同的类型。 Hence it cannot be passed to new ArrayList<List<String>>() that takes a bounded type as parameter. 因此,它无法传递给新的ArrayList<List<String>>() ,它将有界类型作为参数。

List<List<String>> is not same as List<List<?>> . List<List<String>>List<List<?>> Generics are invariant in nature. 泛型在本质上是不变的。 If you only do List<?> and pass List<String> then it will work because List of Anything can be represented by Lists of String . 如果您只执行List<?>并传递List<String>那么它将起作用,因为List of Anything可以由Lists of StringLists of String表示。

But List of List of anything can not be represented by List of List of String . 但是List of List of anything能用List of List of String来表示。

@Lukas Elder has already specified case that will work. @Lukas Elder已经指定了@Lukas Elder案例。 Here is the second case that will work 这是第二个可行的案例

private static void fourth(List<?> a){
    System.out.println("List of anything ");
}
List<List<?>> == List {                 //That contains any unknown type lists
                        List<Integer>,
                        List<String>,
                        List<Object>
                      }

Where as 在哪里

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

So here 所以在这里

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

Hence List<? extends List<?> 因此List<? extends List<?> List<? extends List<?> is super type of List<List<String>> and assignable. List<? extends List<?>List<List<String>>超类型,可分配。

So valid value to call your fourth method is below. 因此,调用fourth方法的有效值如下。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM