[英]Assigning Integer to Object allowed but assigning Integer array to Object array not allowed?
我正在阅读如何将子类对象分配给父类容器。 下面列出了3种情况。 对于集合,数组和普通对象。 我对这三种情况感到困惑,因为这三种情况以及为什么这三种情况在Java中的处理方式不同。 请问以下情况有简单的解释吗? 它们似乎是非常基本的Java概念,不知道为什么让我感到困惑。
这样会产生编译时错误。
List<Object> objectList = new ArrayList<Integer>();//compile time error
但是,这是允许的
Object object = new Integer(9); object = 1.2;// no run time error
但这不是吗? (尽管从技术上讲编译器允许,但会出现运行时错误)
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
。
ArrayList<Integer>
不是List<Object>
。 ArrayList<Object>
是。
您创建一个Integer
并将其分配给一个Object
变量。 您不能将double
分配给Object
,因为double
是原始类型,并且不会从Object
继承。 您可以指定一个Double
。
您创建单个元素的Integer
数组,并将其分配给Object
数组的变量。 然后,您尝试为Integer
元素分配一个值,该值不是Integer
。
编辑:
正如davman解释的那样,我对2.的回答是不正确的,object = 1.2; 由于装箱而实际上是有效的代码。
进一步说明:
任何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>
的不一致引起的。 编译器会通过编译时错误防止这种不一致。
即使您有一个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.