[英]Java generics Strange behavior
In Java Integer extends Number 在Java中, 整数扩展Number
Then next code is compiling: 然后下一个代码正在编译:
List<Number> list1 = null;
List<? super Integer> list2 = null;
list2 = list1;
While this code is not compiling: 虽然此代码未编译:
List<? super Number> list1 = null;
List<? extends Integer> list2= null;
list1 = list2;
The question is why? 问题是为什么?
Let's see what would go wrong if it would have compiled: 让我们看看如果编译后会出什么问题:
// Suppose list1, and list2 are initialized like this
List<? super Number> list1 = new ArrayList<Object>(); // valid assignment
List<? extends Integer> list2 = new ArrayList<Integer>(); // valid
// had this been valid, list1 and list2 both point to ArrayList<Integer>
list1 = list2;
// This is fine, as list1 declared type is `List<? super Number>`
list1.add(new Float(2.4f));
// The below code will compile fine, as list2.get(0) type is Integer.
// But it would throw ClassCastException at runtime.
Integer in = list2.get(0);
So, to avoid it runtime, compiler gives you a compile time error. 因此,为避免运行时,编译器会给您一个编译时错误。
For the first case however, you have somehow reversed the assignment, so the comparison between the 2 codes doesn't make sense. 但是,对于第一种情况,您已经以某种方式取消了分配,因此这两个代码之间的比较没有意义。 Change the first code to:
将第一个代码更改为:
List<Number> list1 = null;
List<? super Integer> list2 = null;
list1 = list2;
and it will fail too. 它也会失败。
Also, reversing the assignment in the 2nd code would also make the code fail to compile. 同样,反转第二代码中的分配也将使代码无法编译。
Some explanation: 一些解释:
What you must remember is, a super class reference can point to a subclass object, but not the reverse. 您必须记住的是,超类引用可以指向子类对象,但不能指向相反的对象。 If all the lists that can be capture-converted from
list1
are also capture convertible from the declared type of list2
, then the assignment list2 = list1
would be valid, else it would fail to compile. 如果所有可以从
list1
捕获转换的列表也都可以从list2
的声明类型捕获转换,则分配list2 = list1
将有效,否则将无法编译。
For the first code: 对于第一个代码:
List<? super Integer>
List<? super Integer>
can be capture converted to the following lists: List<? super Integer>
转换为以下列表:
List<Integer>
List<Number>
List<Object>
List<Serializable>
Since List<Number>
is there in the list, so assignment list2 = list1
is valid, as list1
can only point to a List<Number>
. 由于
List<Number>
中存在List<Number>
,因此分配list2 = list1
有效,因为list1
只能指向List<Number>
。 But, the reverse assignment list1 = list2
is not valid, as List<Integer>
is not a subtype of List<Number>
. 但是,反向分配
list1 = list2
无效,因为List<Integer>
不是List<Number>
的子类型。
Similarly, for the 2nd code: 同样,对于第二个代码:
List<? super Number>
List<? super Number>
can be capture-converted to: List<? super Number>
可以捕获转换为:
List<Object>
List<Serializable>
List<Number>
List<? extends Integer>
List<? extends Integer>
can be capture-converted to: List<? extends Integer>
可以捕获转换为:
List<Integer>
Since List<Integer>
is not capture-convertible from List<? super Number>
由于
List<Integer>
不能从List<? super Number>
捕获转换List<? super Number>
List<? super Number>
, so list1 = list2
is invalid. List<? super Number>
,所以list1 = list2
无效。
Also, since List<Object>
and all other lists are not capture-convertible from List<? extends Integer>
另外,由于
List<Object>
和所有其他列表不能从List<? extends Integer>
捕获转换List<? extends Integer>
List<? extends Integer>
, so list2 = list1
is also invalid. List<? extends Integer>
,所以list2 = list1
也是无效的。
(1) In the first example, List<Number>
is "captured" by of List<? super Integer>
(1)在第一个示例中,
List<Number>
被List<? super Integer>
所“捕获” List<? super Integer>
List<? super Integer>
. List<? super Integer>
。 A List<Number>
is a List<? super Integer>
List<Number>
是List<? super Integer>
List<? super Integer>
. List<? super Integer>
。
(2) But in the second example, List<? extends Integer>
(2)但在第二个示例中,
List<? extends Integer>
List<? extends Integer>
is not captured by List<? super Number>
List<? extends Integer>
不能被List<? super Number>
捕获List<? super Number>
List<? super Number>
. List<? super Number>
。
For example, you can add Number
s to List<? super Number>
例如,您可以将
Number
添加到List<? super Number>
List<? super Number>
, but you cannot add non- Integer
Number
s to List<? extends Integer>
List<? super Number>
,但是不能将非Integer
Number
添加到List<? extends Integer>
List<? extends Integer>
. List<? extends Integer>
。
List<? super Number> list1 = new ArrayList<Number>();
list1.add(0.5); //okay
List<? extends Integer> list2 = new ArrayList<Integer>();
list2.add(0.5); //not okay
Therefore, you cannot assign list1
to be list2
, since list2
does not support everything that the type of list1
should. 因此,您不能将
list1
分配为list2
,因为list2
不支持list1
类型应具备的所有功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.