[英]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 areheterogeneous
and compiler cannot guarantee that all object inList<List<?>>
are of same type.这意味着类型是未知的,任何类型的对象都可以添加到
heterogeneous
List<List<?>>
,编译器不能保证List<List<?>>
中的所有对象都是相同的类型。 Hence it cannot be passed to newArrayList<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 String
的Lists 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.