【问题标题】:Differences between cast arraylist and cast array in java [duplicate]java中cast arraylist和cast array之间的区别[重复]
【发布时间】: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 感谢您的提醒

标签: java arrays arraylist casting


【解决方案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。因此,它们是“完全成熟的对象”。毫无疑问。
    猜你喜欢
    • 2015-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-13
    • 2012-07-24
    • 2013-07-11
    • 2013-12-20
    • 1970-01-01
    相关资源
    最近更新 更多