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

Java 为什么我可以将一种类型的数组存储在另一种类型的变量中?,java,arrays,generics,Java,Arrays,Generics,对于泛型,您不能: Object[] arr1 = new String[]{"0"}; CharSequence[] arr2 = new String[]{"0"}; arr1[0] = 0; // compiles; causes exception at runtime //java.util.ArrayList list1=new java.util.ArrayList();不会编译 Java中的每个类都是对象的子类。由于arr1是一个Object项的数组,因此它可以接受任何内容,包

对于泛型,您不能:

Object[] arr1 = new String[]{"0"};
CharSequence[] arr2 = new String[]{"0"};
arr1[0] = 0; // compiles; causes exception at runtime
//java.util.ArrayList list1=new java.util.ArrayList();不会编译

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

Java中的每个类都是
Object
类的子类。由于
arr1
是一个
对象的数组
项,它可以接受任何东西,包括字符串和整数。

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


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

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


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

泛型和数组:不同的规则。

当数组为时,泛型集合不可重新定义
这意味着在运行时,JVM将编译的
列表
视为
列表
实例,而JVM将编译的
字符串[]
视为
字符串
实例的数组

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

// java.util.ArrayList<CharSequence> list1 = new java.util.ArrayList<String>(); won't compile
但由于擦除,在运行时无法对泛型执行相同的检查。

因此,JLS在编译时对泛型的限制更大。

因此,
数组是协变的,而泛型集合是不变的。

泛型和数组:规则不同。

当数组为时,泛型集合不可重新定义
这意味着在运行时,JVM将编译的
列表
视为
列表
实例,而JVM将编译的
字符串[]
视为
字符串
实例的数组

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

// java.util.ArrayList<CharSequence> list1 = new java.util.ArrayList<String>(); won't compile
但由于擦除,在运行时无法对泛型执行相同的检查。

因此,JLS在编译时对泛型的限制更大。
因此,
数组
是协变的,而泛型集合是不变的