繁体   English   中英

允许将整数分配给对象,但是不允许将整数数组分配给对象数组吗?

[英]Assigning Integer to Object allowed but assigning Integer array to Object array not allowed?

我正在阅读如何将子类对象分配给父类容器。 下面列出了3种情况。 对于集合,数组和普通对象。 我对这三种情况感到困惑,因为这三种情况以及为什么这三种情况在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) 

如果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. ArrayList<Integer>不是List<Object> ArrayList<Object>是。

  2. 您创建一个Integer并将其分配给一个Object变量。 您不能将double分配给Object ,因为double是原始类型,并且不会从Object继承。 您可以指定一个Double

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

编辑:

正如davman解释的那样,我对2.的回答是不正确的,object = 1.2; 由于装箱而实际上是有效的代码。

进一步说明:

  1. 任何Integer都是Object ,但Object不一定是Integer 您可以期望能够将任何Object添加到List<Object> ,但是只能将Integer值添加到ArrayList<Integer> 现在,如果您将ArrayList<Integer>分配给List<Object> ,则稍后您可以尝试将Double添加到List<Object> ,这与List<Object>完全有效。 但是由于您在操作无效的地方存储了ArrayList<Integer> ,因此该操作将失败。 此失败是由于将ArrayList<Integer>分配给List<Object>的不一致引起的。 编译器会通过编译时错误防止这种不一致。

  2. 即使您有一个Object数组,也不会改变您内部拥有Integer的事实。 你尝试分配一个值, Integer ,这是无效的Integer秒。

在第一行中,您必须编写:

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

然后就可以了。 ? extends Object ? extends Object表示列表包含? extends Object的元素,例如Integer。

如果使用? 此处给出的操作符,那么您将不再具有add方法。 因此,您需要首先在ArrayList添加所有元素,然后再分配它:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM