[英]Java wrapped generics compilation error
I have a very basic code to reproduce the issue: 我有一个非常基本的代码来重现该问题:
public class Main {
public static <T extends Number> void bar(Wrapper<List<T>> wrapper) {
// do something
}
public static void foo(Wrapper<List<? extends Number>> wrapper) {
// do something
}
public static <T extends Number> void bar2(List<T> aList) {
// do something
}
public static void foo2(List<? extends Number> aList) {
// do something
}
public static void main(String[] args) {
List<Integer> aList = Collections.singletonList(1);
foo2(aList); // compiles
bar2(aList); // compiles
Wrapper<List<Integer>> wrapper = new Wrapper<>(Collections.singletonList(1));
foo(wrapper); // not compiles
bar(wrapper); // compiles
}
private static class Wrapper<T> {
private final T t;
public Wrapper(T t) {
this.t = t;
}
}
}
So the question is why javac gives an error when I try to compile the code: 所以问题是为什么当我尝试编译代码时,javac为什么会给出错误:
Main.java:26: error: method foo in class Main cannot be applied to given types;
foo(wrapper); // not compiles
^
required: Wrapper<List<? extends Number>>
found: Wrapper<List<Integer>>
reason: argument mismatch; Wrapper<List<Integer>> cannot be converted to Wrapper<List<? extends Number>>
1 error
Because Java generics are not covariant. 因为Java泛型不是协变的。
In your case 就你而言
Wrapper<List<Integer>>
instance cannot be used as 实例不能用作
Wrapper<List<? extends Number>>
parameter because 参数,因为
List<Integer>
does not extend 不扩展
List<? extends Number>
Wrapper<List<Integer>>
is not a subtype of Wrapper<List<? extends Number>>
Wrapper<List<Integer>>
不是Wrapper<List<? extends Number>>
的子类型Wrapper<List<? extends Number>>
Wrapper<List<? extends Number>>
. Wrapper<List<? extends Number>>
。
Use Wrapper<? extends List<? extends Number>>
使用Wrapper<? extends List<? extends Number>>
Wrapper<? extends List<? extends Number>>
Wrapper<? extends List<? extends Number>>
. Wrapper<? extends List<? extends Number>>
。
To see why you can't pass Wrapper<List<Integer>>
to foo
, consider the following: I've replaced Wrapper
with List
, but it's the same thing from a type safety point of view. 要了解为什么不能将Wrapper<List<Integer>>
传递给foo
,请考虑以下事项:我已经用List
替换了Wrapper
,但是从类型安全的角度来看这是同一回事。
List<List<? extends Number>> list = new ArrayList<>();
List<List<Integer>> intList = new ArrayList<>();
So, you can add something to list
: 因此,您可以在list
添加一些内容:
List<Double> doubles = new ArrayList<>(Arrays.asList(0.0));
list.add(doubles);
But, if you were able to write this assignment: 但是,如果您能够编写此作业:
list = intList;
Then calling list.add(doubles)
would mean there would then be a List<Double>
in intList
. 然后调用list.add(doubles)
意味着intList
中将存在一个List<Double>
。 This is not type safe, and thus forbidden. 这不是类型安全的,因此被禁止。
However, if list
has type List<? extend List<? extends Number>>
但是,如果list
类型为List<? extend List<? extends Number>>
List<? extend List<? extends Number>>
List<? extend List<? extends Number>>
, then you can't invoke add
on it, so you can't get into this situation, so that would be safe. List<? extend List<? extends Number>>
,那么您将无法在其上调用add
,所以您将无法进入这种情况,因此这是安全的。
Because List<Integer>
is not a subclass of List<? extends Number>
因为List<Integer>
不是List<? extends Number>
的子类List<? extends Number>
List<? extends Number>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.