java中cast arraylist和cast array之间的区别[重复]
Posted
技术标签:
【中文标题】java中cast arraylist和cast array之间的区别[重复]【英文标题】:Differences between cast arraylist and cast array in java [duplicate] 【发布时间】:2014-08-18 06:05:56 【问题描述】:正如乔恩对此post 的回答所说,如果编译器允许这种转换(如下所示),那么稍后添加一些其他对象对程序来说可能是一件坏事。
ArrayList<String> temList = new ArrayList<String>();
ArrayList<Object> obList = (ArrayList<Object>)temList;//compile error
//obList.add(1); --bad
但让我困惑的是为什么在相同的情况下,数组有不同的行为。
String[] strings = new String[10];
Object[] temp = (Object[])strings;//nothing happens
那么谁能解释一下这里的区别是什么以及为什么java会做出这样的设计?谢谢。
编辑:一个类似的question
【问题讨论】:
@user3580294 感谢您的提醒 【参考方案1】:如果数组的组件类型可分配给已分配数组的组件类型,则数组被设计为允许协变分配。类型检查是由 JVM 在运行时完成的,如果尝试将值存储在不兼容的数组中,则会抛出 ArrayStoreException
。使用得当,这可以表达数组的协变类型,这通常很方便。
但是,这种语言特性可能会导致分散的运行时异常,Sun 不想为 Java 5 引入的泛型类型分配重复这些异常。相反,Sun 希望在编译时发现这种无效使用。这似乎特别重要,因为泛型引入了比数组类型更复杂的类型系统组件,因此如果 Sun 做出不同的决定,类似于 ArrayStoreException
的运行时错误肯定会变得更加普遍。相反,对于泛型,协变和逆变问题由通配符解决,允许在编译时而不是运行时发现类型错误。
【讨论】:
【参考方案2】:数组不是 100% 的对象,它们是平凡的对象。但是ArrayList
100% 的对象。
如果您尝试将 Integer 分配给 temp 数组,它将抛出 ArrayStoreException
。
所以转换数组很好。
但是将ArrayList
转换为底层ArrayList 实现只能保存一个字符串(子类)的超级对象会在运行时引起问题。
感谢泛型,编译器可以在它发生之前识别它并显示编译器错误。这是一个很好的设计,否则程序会在运行时失败。
在 Java 1.5 泛型之前
List list = new ArrayList();
list.add(1);
list.add("One");
list.add(100l);
编码人员必须进行大量instanceof
检查是合法的。他们未能检查程序在运行时崩溃的地方。
【讨论】:
半无关的问题,为什么人们认为 javascript 能够在数组中存储不同类型的对象的能力是积极的?它在 Java 中基本上用作 Object[],只是没有强制转换。我认为这是一种编码风险。 @shazin 对不起,平凡的对象是什么意思?有什么例子或参考吗?以及为什么数组不会使这种类型的转换成为编译器错误。谢谢。 @Tony 这意味着它不是 100% 的对象,因为它没有任何功能,但它有一个像“长度”这样的字段。它不仅仅是一个前导变量,但还不是一个成熟的对象。 @shazin 嗯,数组扩展Object
。因此,它们是“完全成熟的对象”。毫无疑问。以上是关于java中cast arraylist和cast array之间的区别[重复]的主要内容,如果未能解决你的问题,请参考以下文章
使用redis时出现java.util.ArrayList cannot be cast to java.lang.Long
PageHelper分页异常(java.base/java.util.ArrayList cannot be cast to com.github.pagehelper.Page)
Type safety: Unchecked cast from Object to ArrayList
何时在 Linq 中使用 Cast() 和 Oftype()