有人能给我解释一下为什么在下面的代码示例中标记为//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;
}
}
具体地说,当我们说bList
是ArrayList<B>
类型时,不是意味着它的每个元素都是B
的一个实例吗?如果是这样,那么如果我们可以将B
的单个实例转换为A
,那么将其转换为A
又有什么问题呢
谢谢。
发布于 2011-05-18 12:07:02
问题是:
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?
如果你对数组做同样的事情,你会在运行时在第4行得到一个ArrayStoreException。对于泛型集合,决定在编译时防止这种情况。
发布于 2011-05-18 12:03:26
因为泛型是严格的。它们不是协变的
ArrayList<A>
aList只能引用A
类型的ArrayList
来自wiki
与数组不同,泛型类既不是协变的,也不是逆变的。例如,
List<String>
和List<Object>
都不是另一个的子类型:
// a是字符串列表a= new ArrayList()的单元素列表;a.add("foo");// b是对象列表b= a;//这是编译时错误
但是,泛型类型参数可以包含通配符(这是仅使用一次的额外类型参数的快捷方式)。示例:给定对任何对象的列表进行操作的方法的要求,那么可以在对象上执行的唯一操作是那些类型关系可以保证安全的操作。
// a是字符串列表的单元素列表a= ArrayList();a.add("foo");// b是任意元素的列表List b= a;//检索第一个元素对象c= b.get(0);//这是合法的,因为我们可以保证//返回类型"?“是Object的子类型//将整数添加到b. b.add(new Integer (1));//这是编译时错误;//我们不能保证Integer是//参数类型的子类型"?“
还可以绑定通配符,例如,上界和下界分别为"? extends Foo
“或"? super Foo
”。这允许改进允许的性能。示例:给定协方差,则可以检索元素并将其安全地分配给Foo
类型(协方差)。在给定List<? super Foo>
的情况下,可以安全地将Foo
对象添加为元素(Contravariance)。
发布于 2011-05-18 12:09:54
阿尼梅什
即使类B是A的子类型,ArrayList< B >也不是ArrayList 的子类型。它和B[]在同一行上,不是A[]的子类型。这是两个独立的不相关的类型。
https://stackoverflow.com/questions/6044329
复制