为什么将ArrayList的泛型转换为超类不起作用?

Ani*_*esh 8 java generics casting

有人可以向我解释为什么//this line gives a compile error (why?)以下代码示例中标记的行不起作用?

import java.util.ArrayList;

public class GenericCastCheck {

    class A{
    }

    class B extends A{
    }

    public static void main(String[] args) {

        A aObject = new A();
        B bObject = new B();

        //this line works fine
        aObject = bObject;
        //this line gives a compile (expected)
        bObject = aObject;

        ArrayList<A> aList = new ArrayList<A>();
        ArrayList<B> bList = new ArrayList<B>();

        //this line gives a compile error (why?)
        aList = bList;
        //this line gives a compile error (expected)
        bList = aList;
    }
}
Run Code Online (Sandbox Code Playgroud)

具体来说,当我们说它bList是类型时ArrayList<B>,是否并不意味着它的每个元素都是一个实例B?如果是这样,那么它是什么铸造的问题ArrayList<A>,如果我们都可以投射单个实例BA

谢谢.

Mic*_*rdt 10

问题是这样的:

ArrayList<A> aList = new ArrayList<A>();
ArrayList<B> bList = new ArrayList<B>();
aList = bList; // if this were valid...
aList.add(new A()); // ...what should happen here?
B b = bList.get(0); // ...and here?
Run Code Online (Sandbox Code Playgroud)

如果对数组执行相同的操作,则会在运行时在第4行中获得ArrayStoreException.对于通用集合,决定在编译时阻止这种事情.


Jig*_*shi 5

因为通用是严格的.他们不是共同的

ArrayList<A>aList只能引用ArrayList类型A


来自维基

与数组不同,泛型类既不是协变的也不是逆变的.例如,既不是List<String>也不 List<Object>是另一个的子类型:

// a is a single-element List of String
List<String> a = new ArrayList<String>();
a.add("foo");

// b is a List of Object
List<Object> b = a; // This is a compile-time error
Run Code Online (Sandbox Code Playgroud)

但是,泛型类型参数可以包含通配符(仅使用一次的额外类型参数的快捷方式).示例:由于需要对任何对象的列表进行操作的方法,因此可以对对象执行的唯一操作是可以保证类型关系安全的操作.

// a is a single-element List of String
List<String> a = new ArrayList<String>();
a.add("foo");

// b is a List of anything
List<?> b = a;

// retrieve the first element
Object c = b.get(0);
// This is legal, because we can guarantee
// that the return type "?" is a subtype of Object

// Add an Integer to b.
b.add(new Integer (1)); 
// This is a compile-time error; 
// we cannot guarantee that Integer is
// a subtype of the parameter type "?"
Run Code Online (Sandbox Code Playgroud)

通配符也可以分别绑定,例如" ? extends Foo"或" ? super Foo"用于上限和下限.这允许改进允许的性能.示例:给定a List<? extends Foo>,然后可以检索元素并将其安全地分配给Foo 类型(协方差).给定a List<? super Foo>,则Foo可以安全地添加对象作为元素(逆变).