Java 将Y添加到集合<;X>;,Y不是X的实例。为什么没有引发运行时异常?

Java 将Y添加到集合<;X>;,Y不是X的实例。为什么没有引发运行时异常?,java,generics,collections,Java,Generics,Collections,以下方法将any添加到any集合中。为什么没有引发运行时异常 publicstaticvoidaddanything(Collection,因为编写的方法是将Object类型的实例添加到T的超类型的列表中(您肯定知道,对于任何T,Object都是T的超类型)。因此,该方法将您的列表视为一个列表,并向其中添加对象实例。这显然是有效的行为。如果您将非字符串对象添加到列表中,并尝试对其内容执行某些操作,您将看到异常。运行时不会因为您的而引发异常rrayList的编译方式与非泛型的ArrayList类似

以下方法将any添加到any集合中。为什么没有引发运行时异常


publicstaticvoidaddanything(Collection,因为编写的方法是将Object类型的实例添加到T的超类型的列表中(您肯定知道,对于任何T,Object都是T的超类型)。因此,该方法将您的
列表
视为一个
列表
,并向其中添加对象实例。这显然是有效的行为。如果您将非字符串对象添加到列表中,并尝试对其内容执行某些操作,您将看到异常。

运行时不会因为您的
而引发异常rrayList
的编译方式与非泛型的
ArrayList
类似,这意味着您可以向其中添加任何对象。

两个原因:向后兼容性和性能

为了向后兼容旧的、不安全的代码,Java中的泛型是通过“类型擦除”实现的。类型系统仅在编译时强制执行。当您使用类型转换时,您告诉编译器“这很好,我知道我在做什么”,而您只得到一个警告

在运行时添加对象时检查对象的类型将是一种性能回归。目前,
ArrayList.add
不需要了解所添加对象的任何信息:它只与对象引用一起工作。这意味着不需要将对象本身的任何信息从主存加载到CPU寄存器或cach中e、 如果必须检查对象的类型,则 会急剧增加,这会减慢程序

如果需要确保只添加字符串的列表,可以使用
集合。checkedList
方法:

List<String> list = Collections.checkedList(new ArrayList<>(), String.class);
addAnything(list, 2); // run time error
List List=Collections.checkedList(新的ArrayList(),String.class);
addAnything(列表,2);//运行时错误
“为什么添加过程中没有ClassCastException?…为什么这段代码中没有抛出任何异常?…”

因为


您的代码如下所示:“尽管代码编译时没有错误,但它会引发运行时异常(java.lang.ClassCastException)…”

通过设计向后兼容。不要欺骗编译器。