[英]Java generics Strange behavior
让我们看看如果编译后会出什么问题:
// 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);
因此,为避免运行时,编译器会给您一个编译时错误。
但是,对于第一种情况,您已经以某种方式取消了分配,因此这两个代码之间的比较没有意义。 将第一个代码更改为:
List<Number> list1 = null;
List<? super Integer> list2 = null;
list1 = list2;
它也会失败。
同样,反转第二代码中的分配也将使代码无法编译。
一些解释:
您必须记住的是,超类引用可以指向子类对象,但不能指向相反的对象。 如果所有可以从list1
捕获转换的列表也都可以从list2
的声明类型捕获转换,则分配list2 = list1
将有效,否则将无法编译。
对于第一个代码:
List<? super Integer>
可以捕获List<? super Integer>
转换为以下列表:
List<Integer>
List<Number>
List<Object>
List<Serializable>
由于List<Number>
中存在List<Number>
,因此分配list2 = list1
有效,因为list1
只能指向List<Number>
。 但是,反向分配list1 = list2
无效,因为List<Integer>
不是List<Number>
的子类型。
同样,对于第二个代码:
List<? super Number>
List<? super Number>
可以捕获转换为:
List<Object>
List<Serializable>
List<Number>
List<? extends Integer>
List<? extends Integer>
可以捕获转换为:
List<Integer>
由于List<Integer>
不能从List<? super Number>
捕获转换List<? super Number>
List<? super Number>
,所以list1 = list2
无效。
另外,由于List<Object>
和所有其他列表不能从List<? extends Integer>
捕获转换List<? extends Integer>
List<? extends Integer>
,所以list2 = list1
也是无效的。
(1)在第一个示例中, List<Number>
被List<? super Integer>
所“捕获” List<? super Integer>
List<? super Integer>
。 List<Number>
是List<? super Integer>
List<? super Integer>
。
(2)但在第二个示例中, List<? extends Integer>
List<? extends Integer>
不能被List<? super Number>
捕获List<? super Number>
List<? super Number>
。
例如,您可以将Number
添加到List<? super Number>
List<? super Number>
,但是不能将非Integer
Number
添加到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
因此,您不能将list1
分配为list2
,因为list2
不支持list1
类型应具备的所有功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.