允许将Integer分配给Object但是不允许将Integer数组分配给Object数组?

时间:2016-08-27 08:26:34

标签: java arrays object inheritance

我正在阅读如何将子类对象分配给父类容器。下面列出了3种情况。对于集合,数组和普通对象。关于如何和& amp;为什么这三个在Java中的处理方式不同。请问下面的场景有简单的解释吗?它们似乎是非常基本的java概念,不知道为什么让我感到困惑。

  1. 这会产生编译时错误。

    List<Object> objectList = new ArrayList<Integer>();//compile time error
    
  2. 但是,这是允许的

    Object object = new Integer(9);
    object = 1.2;// no run time error
    
  3. 但这不是吗? (但是,技术上编译器允许,但我们得到运行时错误)

    Object objectArr[] = new Integer[1];
    objectArr[0] = 1.2;// run time error (Exception in thread "main" java.lang.ArrayStoreException: java.lang.Double)
    

3 个答案:

答案 0 :(得分:2)

如果A是B的子类型,则可以将类型A的内容分配给类型B的变量。一般来说,对于非基本类型,这意味着A必须支持所有的操作B确实。

看看你的例子:

首先:

List<Object> objectList = new ArrayList<Integer>();//compile time error

是的,因为ArrayList<Integer>不是List<Object>;您无法为其添加Object。考虑:

List<Object> l = new ArrayList<Object>();
List<Integer> l2 = new ArrayList<Integer>();
l.add(new Object()); // ok
l2.add(new Object()); // not ok; `List<Integer>` doesn't support this.

因此,您看到List<Integer>(或ArrayList<Integer>)不是List<Object>的子类型 - 因为它不支持所有相同的操作。

下一步:

Object object = new Integer(9);
object = 1.2;// no run time error

在这种情况下,值1.2会自动装入包装类型Double(全名java.lang.Double)。由于这是Object的子类,因此分配工作正常。变量object中存储的内容不是原始double值1.2,而是对包含原始值的Double对象的引用。

最后:

Object objectArr[] = new Integer[1];
objectArr[0] = 1.2;// run time error (Exception in thread "main" java.lang.ArrayStoreException: java.lang.Double)

这是一个古怪的案例。 Java认为Integer的数组是Object数组的子类型,但是通过普通类型理论不会出现这种情况,因为您无法存储Object(这也不是Integer}这样的数组。另一方面,Integer数组至少支持Object数组所做的所有其他操作 - 您可以检索元素并确保它们是Object的子类型;你可以查看数组长度;因此,您可以将new Integer[1] - Integer数组 - 分配给Object[]类型的变量。

要使这种形式的子类型工作,Integer数组需要实现类似于Object隐式支持的“存储Object[]元素”操作。但是,由于Integer[]仅包含Integer个对象,因此存储操作必须失败 - 因此,如果您尝试存储的内容不是Integer,则会在运行时获得异常。在您的示例中,您将1.2存储为自Double,而不是Integer

答案 1 :(得分:0)

  1. ArrayList<Integer>不是List<Object>的实现。 ArrayList<Object>是。

  2. 您创建了Integer并将其分配给Object变量。您无法将double分配给Object,因为double是基本类型,并且不会从Object继承。您可以指定Double

  3. 您创建单个元素的Integer数组,并将其分配给Object数组的变量。然后,您尝试为Integer元素指定一个值,该值不是Integer

  4. 编辑:

    正如达夫曼解释的那样,我对2的回答是不正确的,对象= 1.2;由于boxing,实际上是有效的代码。

    进一步解释:

    1. 任何Integer都是Object,但Object不一定是Integer。您可以将Object添加到List<Object>,但是只能将Integer值添加到ArrayList<Integer>。现在,如果您将ArrayList<Integer>分配给List<Object>,那么稍后您可能会尝试将Double添加到List<Object>,这对{{1}完全有效}}。但由于您存储了List<Object>,操作无效,操作将失败。此失败是由于将ArrayList<Integer>分配给ArrayList<Integer>的不一致。编译器会保护您免受与编译时错误的不一致。

    2. 即使您拥有List<Object>数组,也不会改变其中包含Object的事实。并且您尝试为Integer分配一个值,该值对Integer无效。

答案 2 :(得分:0)

在第一行中你必须写:

List<? extends Object> objectList = new ArrayList<Integer>();

然后它的工作原理。 ? extends Object表示List包含扩展Object的元素,例如整数。

如果您使用此处给出的?运算符,那么您将不再拥有add方法。因此,您首先需要添加ArrayList中的所有元素并稍后再分配:

ArrayList<Integer> al = new ArrayList<>();
al.add(3);
...
List<? extends Object> objectList = al;