繁体   English   中英

Java泛型行为异常

[英]Java generics Strange behavior

在Java中, 整数扩展Number

然后下一个代码正在编译:

List<Number> list1 = null;
List<? super Integer> list2 = null;
list2 = list1;

虽然此代码未编译:

List<? super Number> list1 = null;
List<? extends Integer> list2= null;
list1 = list2;

问题是为什么?

让我们看看如果编译后会出什么问题:

// 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.

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