Java泛型奇怪的行为

时间:2013-11-23 08:35:28

标签: java generics

在Java中Integer扩展Number

然后下一个代码是编译:

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

虽然此代码未编译:

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

问题是为什么?

2 个答案:

答案 0 :(得分:5)

让我们看看如果编译它会出错:

// 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);  

因此,为避免运行时,编译器会给出编译时错误。

然而,对于第一种情况,您以某种方式颠倒了分配,因此2代码之间的比较没有意义。将第一个代码更改为:

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

它也会失败。

此外,在第二个代码中反转赋值也会使代码无法编译。

一些解释:

你必须记住的是,超类引用可以指向子类对象,但不能反过来。如果可以从list1捕获转换的所有列表也可以从声明的list2类型中捕获转换,则赋值list2 = list1将是有效的,否则将无法编译。

第一个代码:

  • List<? super Integer>可以被捕获转换为以下列表:
    • List<Integer>
    • List<Number>
    • List<Object>
    • List<Serializable>

由于列表中有List<Number>,因此作业list2 = list1有效,因为list1只能指向List<Number>。但是,反向分配list1 = list2无效,因为List<Integer>不是List<Number>的子类型。

同样,对于第二个代码:

  • List<? super Number>可以被捕获转换为:

    • List<Object>
    • List<Serializable>
    • List<Number>
  • List<? extends Integer>可以被捕获转换为:

    • List<Integer>

由于List<Integer>无法从List<? super Number>进行捕获转换,因此list1 = list2无效。

此外,由于List<Object>和所有其他列表无法从List<? extends Integer>进行捕获转换,因此list2 = list1也无效。

答案 1 :(得分:0)

(1)在第一个示例中,List<Number>List<? super Integer>“捕获”。 List<Number>List<? super Integer>

(2)但在第二个示例中,List<? extends Integer>

} <{1}}。

例如,您可以将List<? super Number>添加到Number,但不能将非List<? super Number> Integer添加到Number

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类型的所有内容。