以下代码编译运行成功,没有任何异常
import java.util.ArrayList;
class SuperSample {}
class Sample extends SuperSample {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
try {
ArrayList<Sample> sList = new ArrayList<Sample>();
Object o = sList;
ArrayList<SuperSample> ssList = (ArrayList<SuperSample>)o;
ssList.add(new SuperSample());
} catch (Exception e) {
e.printStackTrace();
}
}
}
不应该是 ArrayList<SuperSample> ssList = (ArrayList<SuperSample>)o;
行吗?产生一个 ClassCastException
?
虽然下面的代码会产生一个编译时错误错误来防止堆污染,但上面提到的代码不应该在运行时进行类似的预防吗?
ArrayList<Sample> sList = new ArrayList<Sample>();
ArrayList<SuperSample> ssList = (ArrayList<SuperSample>) sList;
编辑:
如果 Type Erasure 是这背后的原因,难道不应该有额外的机制来防止将无效对象添加到列表中吗?例如
String[] iArray = new String[5];
Object[] iObject = iArray;
iObject[0]= 5.5; // throws ArrayStoreException
那为什么,
ssList.add(new SuperSample());
不是为了抛出任何异常吗?
最佳答案
不应该,在运行时两个列表具有相同类型的 ArrayList。这叫做 erasure .通用参数不是已编译类的一部分,它们在编译期间都会被删除。从 JVM 的角度来看,您的代码等于:
public static void main(String[] args) {
try {
ArrayList sList = new ArrayList();
Object o = sList;
ArrayList ssList = (ArrayList)o;
ssList.add(new SuperSample());
} catch (Exception e) {
e.printStackTrace();
}
}
基本上,泛型只是通过产生编译时错误和警告来简化开发,但它们根本不影响执行。
编辑:
嗯,这背后的基本概念是 Reifiable Type .我强烈推荐阅读本手册:
A reifiable type is a type whose type information is fully available at runtime. This includes primitives, non-generic types, raw types, and invocations of unbound wildcards.
Non-reifiable types are types where information has been removed at compile-time by type erasure
简而言之:数组是可修改的,而泛型集合不是。因此,当您将 smth 存储在数组中时,JVM 会检查类型,因为数组的类型在运行时存在。 Array 只是一 block 内存,而 collection 是一个普通的类,可能有任何实现。例如,它可以将数据存储在数据库中或引擎盖下的磁盘上。如果你想更深入,我建议阅读 Java Generics and Collections书。
关于java - 这段代码不应该产生 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20143558/