如何解决将Y添加到Collection <X>,将Y添加为X的instanceof为什么不抛出运行时异常?
以下方法将任何内容添加到任何集合中。为什么没有抛出运行时异常?
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中的泛型通过“类型擦除”实现。类型系统仅在编译时强制执行。当您使用类型强制转换时,您会告诉编译器“这很好,我知道我在做什么”,您只会收到警告。
在运行时添加对象时检查对象的类型将导致性能下降。目前,ArrayList.add
不需要了解有关所添加对象的任何信息:它仅适用于对象 reference 。这意味着不需要将对象本身从主存储器加载到CPU寄存器或缓存中。如果必须检查对象的类型,则
cache misses会急剧增加,这会使程序变慢。
如果要确保只添加字符串的列表,可以使用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实例。这显然是有效的行为。如果您将非字符串对象添加到列表中并尝试对其内容进行处理,则会看到异常。
运行时不会由于type erasure引发异常。基本上,您的ArrayList<String>
就像非泛型的ArrayList
一样被编译,这意味着您可以向其中添加任何对象。
„
为什么添加过程中没有ClassCastException?…为什么这段代码中没有抛出任何异常?…”
因为generics are checked at compile-time。
您的代码就像the code in this classic example。就像它说的那样:“ 尽管代码编译没有错误,但它会抛出运行时异常( java.lang.ClassCastException ) ...”
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。