[英]Add Y to Collection<X>, and Y not instanceof X. Why is no runtime exception thrown?
以下方法将任何内容添加到任何集合。 为什么没有抛出运行时异常?
public static <T> void addAnything(Collection<? super T> c, Object t) {
c.add((T) t);
}
例如,
List<String> list = new ArrayList<>();
addAnything(list, "ok");
addAnything(list, 2);
addAnything(list, true);
addAnything(list, new Object())
addAnything(list, new Anything())
为什么这段代码没有抛出任何异常?
两个原因:向后兼容性和性能。
为了向后兼容旧的、不安全的代码,Java 中的 generics 是通过“类型擦除”实现的。 类型系统仅在编译时强制执行。 当您使用类型转换时,您是在告诉编译器“这很好,我知道我在做什么”,您只会得到一个警告。
在运行时添加对象时检查对象的类型会导致性能下降。 目前, ArrayList.add
不需要知道关于添加的 object 的任何信息:它只适用于 object参考。 这意味着 object 本身不需要从主 memory 加载到 CPU 寄存器或缓存中。 如果必须检查 object 的类型,缓存未命中的次数将急剧增加,从而减慢程序速度。
如果你想要一个确保只添加字符串的列表,你可以使用Collections.checkedList
方法:
List<String> list = Collections.checkedList(new ArrayList<>(), String.class);
addAnything(list, 2); // run time error
因为所写的方法旨在将类型 Object 的实例添加到任何 T 超类型的列表中(而且您肯定知道,对于任何 T,Object 都是 T 的超类型)。 因此,该方法将您的List<String>
视为List<Object>
并向其添加 Object 的实例。 这显然是有效的行为。 如果您将非 String 对象添加到列表并尝试对其内容执行某些操作,您将看到异常。
由于类型擦除,运行时不会抛出异常。 基本上你的ArrayList<String>
就像非泛型ArrayList
一样被编译,这意味着你可以向它添加任何对象。
„
为什么添加过程中没有ClassCastException?……为什么这段代码没有抛出任何异常?…… ”
您的代码就像这个经典示例中的代码。 就像它在那里说的那样:“虽然代码编译没有错误,但它抛出运行时异常( java.lang.ClassCastException ) ……”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.