Java中为什么不允许直接创建泛型数组

Published: 18 Sep 2014 Category: 技术

失败的方式

在Java中,如果使用泛型数组,会出现编译错误, 例如

List<String>[] stringLists = new List<String>[1];

会提示

Error: Cannot create a generic array of List<String>

那么,在Java中为什么不允许创建泛型数组呢? 《Effective Java》第五章给出了一个解释。

使用泛型的作用是使得程序在编译期可以检查出与类型相关的错误,但是如果使用了泛型数组,这种能力就会受到破坏。

首先,假如我们可以声明这样一个泛型数组。

List<String>[] stringLists = new List<String>[1];

那么,由于在 Java 中,数组是协变(covariant)的,这意味着基类类型的数组可以接收子类类型的数组,例如

Object[] objects = stringLists;

一旦我们这样做之后,就可以通过objects向 stringLists中添加非List类型的数据。

List<Integer> intList = Arrays.asList(1);
objects[0] = intList

随后,再使用 stringList 时,stringList[0] 就会保存 intList, 而使用下面的代码,编译器不会提示错误,但运行时,就会出错。

String str = stringList[0].get(0);

成功的方式

我们可以通过,先擦除类型,再强制转化的方式创建一个泛型数组。

List<String>[] stringLists = (List<String>[])new List[10];

不过,随后你会发现,之前说的所有事情对这个通过编译的语句依然成立,你可以通过数组协变去掉泛型数组的类型,再给它添加一个不同类型 的数据,然后再访问这个数据。然后运行的时候就会出错 。。。

        List<String>[] stringLists = (List<String>[])new List[10];
        Object[] objects = stringLists;
        List<Integer> intList = Arrays.asList(1);
        objects[0] = intList;
        String str = stringLists[0].get(0);