Java 为什么铸造ArrayList';超类的泛型不起作用?

Java 为什么铸造ArrayList';超类的泛型不起作用?,java,generics,casting,Java,Generics,Casting,有人能给我解释一下为什么下面代码示例中标记为//这一行出现编译错误(为什么?)的行不起作用吗 import java.util.ArrayList; public class GenericCastCheck { class A{ } class B extends A{ } public static void main(String[] args) { A aObject = new A(); B bObjec

有人能给我解释一下为什么下面代码示例中标记为
//这一行出现编译错误(为什么?
)的行不起作用吗

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;
    }
}
import java.util.ArrayList;
公共类GenericCastCheck{
甲级{
}
B类扩展了A类{
}
公共静态void main(字符串[]args){
A对象=新A();
B对象=新的B();
//这条线很好用
a对象=b对象;
//此行给出一个编译(预期)
b对象=a对象;
ArrayList aList=新的ArrayList();
ArrayList bList=新的ArrayList();
//这一行给出了一个编译错误(为什么?)
aList=bList;
//此行给出一个编译错误(预期)
布利斯特=伊斯兰主义者;
}
}
具体地说,当我们说
bList
属于
ArrayList
类型时,这不意味着它的每个元素都是
B
的实例吗?如果是这样,那么如果我们可以将
B
的单个实例转换为
A
,那么将其转换为
ArrayList
有什么问题


谢谢。

因为通用性很严格。它们不是共变的

ArrayList

与数组不同,泛型类是 既不是协变的也不是逆变的。 例如,
列表
列表
是 其他:

//a是字符串的单个元素列表
列表a=新的ArrayList();
a、 添加(“foo”);
//b是对象的列表
列表b=a;//这是一个编译时错误
但是,可以使用泛型类型参数 包含通配符(用于 仅使用的额外类型参数 一次)。示例:给定一个需求 对于对列表进行操作的方法, 对于任何对象,则只有 可以在上执行的操作 对象是指 类型关系是可以保证的 为了安全

// 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 "?"
//a是字符串的单个元素列表
列表a=新的ArrayList();
a、 添加(“foo”);
//b是任何东西的清单
清单b=a;
//检索第一个元素
对象c=b.get(0);
//这是合法的,因为我们可以保证
//返回类型“”是对象的子类型
//给b加一个整数。
b、 加(新整数(1));
//这是一个编译时错误;
//我们不能保证整数是正确的
//参数类型“”的子类型
也可以绑定通配符,例如“
?
扩展Foo
”或“
?super Foo
”的 上界和下界。 这允许对允许的数据进行细化 演出示例:给定一个
列表,问题是:

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?
ArrayList aList=new ArrayList();
ArrayList bList=新的ArrayList();
aList=bList;//如果这是有效的。。。
aList.add(新的A());/。。。这里会发生什么?
B=bList.get(0);/。。。这里呢?
如果对数组执行相同的操作,则在运行时第4行会出现ArrayStoreException。对于泛型集合,决定在编译时防止这种情况。

Animesh

即使类B是A的子类型,ArrayList也不是ArrayList的子类型。它与B[]在同一行,不是A[]的子类型。这是两个独立的不相关类型。

因为在Java中,
C
C
之间没有子类型关系,即使
A
B
的超类型,反之亦然

如果您对详细信息感兴趣,请在Wikipedia中查找co-/contra方差


注意,在Java数组中,数组是共变的,这意味着
A[]
B[]
的超类型,如果
A
B
的超类型。这就是为什么有时数组会出现奇怪的强制转换异常

非常感谢。我意识到我应该使用
aList=newarraylist(bList)而不是编译也很好的
aList=bList
。)
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?