为什么我可以将一种类型的数组存储在另一种类型的变量中?

时间:2017-07-29 20:35:29

标签: java arrays generics

Object[] arr1 = new String[]{"0"};
CharSequence[] arr2 = new String[]{"0"};
arr1[0] = 0; // compiles; causes exception at runtime

使用泛型,你不能:

// java.util.ArrayList<CharSequence> list1 = new java.util.ArrayList<String>(); won't compile

3 个答案:

答案 0 :(得分:2)

理论是,因为StringObject的子类,所以可以对其进行扩展,以便String[]可以是子类Object[]

当Java 5出现并且正在设计泛型时,他们发现这是一个坏主意,并努力在泛型中防止它。

答案 1 :(得分:1)

泛型和数组:不一样的规则。

通用集合在数组时不可恢复。
这意味着在运行时,JVM将编译的List<String>视为List实例,而JVM将编译的String[]视为String实例的数组。

在编译时,编译器允许将类型的数组赋值给使用它的超类型声明的数组变量。
它允许它,因为可以在运行时检查存储在数组中的元素的有效性:

Number[] numberArray = {1, 5F};
Integer[] integerArray = {1};
numberArray = integerArray; // compile fine
numberArray[0] = 5;  // fine at runtime as valid type
numberArray[0] = 5F; // exception at runtime as Integer[] should not store Float.

但是由于擦除,不可能在运行时使用泛型进行相同的检查。

因此,JLS在编译时对泛型更具限制性 因此,Arrays是协变的,而泛型集合是不变的。

答案 2 :(得分:0)

Java中的每个类都是Object类的子类。由于arr1Object项的数组,因此它可以包含任何内容,包括字符串和整数。