简体   繁体   English

Java泛型行为异常

[英]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.

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