Java 1.6:创建List <T>的数组

Mik*_*ike 33 java generics

为什么我不能创建List数组?

List<String>[] nav = new List<String>[] { new ArrayList<String>() };
Run Code Online (Sandbox Code Playgroud)

Eclipse说"无法创建List的通用数组"

要么

ArrayList<String>[] nav = new ArrayList<String>[] { new ArrayList<String>() };
Run Code Online (Sandbox Code Playgroud)

Eclipse说"无法创建ArrayList的通用数组"

要么

List<String>[] getListsOfStrings() {
    List<String> groupA = new ArrayList<String>();
    List<String> groupB = new ArrayList<String>();
    return new List<String>[] { groupA, groupB };
}
Run Code Online (Sandbox Code Playgroud)

但我可以这样做:

List[] getLists() {
    return new List[] { new ArrayList(), new ArrayList() };
}
Run Code Online (Sandbox Code Playgroud)

Eclipse说List和ArrayList是原始类型,但它编译...

看起来很简单,为什么它不起作用?

Gur*_*oca 29

好吧,泛型教程给出了你的问题的答案.

数组对象的组件类型可能不是类型变量或参数化类型,除非它是(无界)通配符类型.您可以声明其元素类型是类型变量或参数化类型但不是数组对象的数组类型.

这很烦人,可以肯定.这种限制是必要的,以避免以下情况:

// Not really allowed.
List<String>[] lsa = new List<String>[10];
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
// Unsound, but passes run time store check
oa[1] = li;

// Run-time error: ClassCastException.
String s = lsa[1].get(0);
Run Code Online (Sandbox Code Playgroud)

如果允许参数化类型的数组,则前一个示例将在没有任何未经检查的警告的情况下进行编译,但在运行时仍然失败.我们将类型安全作为仿制药的主要设计目标.

  • "如果允许参数化类型的数组,上面的例子将编译时没有任何未经检查的警告,但在运行时失败." 这不是原因.`Object [] sa = new String [10]; oa [1] = new Integer(3);`也将"编译时没有任何未经检查的警告,但在运行时失败".更重要的一点是它应该在存储时失败,使用ArrayStoreException(因此数组是运行时检查的).但运行时检查无法检查泛型,这就是为什么不允许创建参数化类型数组的原因. (9认同)

Paŭ*_*ann 14

通常,您无法创建泛型类型的数组.

原因是JVM无法检查是否只将正确的对象放入其中(使用ArrayStoreExceptions),因为运行时之间的差异List<String>List<Integer>不存在.

当然,您可以使用原始类型List或未绑定的通配符类型欺骗编译器List<?>,然后将其(使用未经检查的强制转换)强制转换为List<String>.但是,你有责任只把List<String>它放在其中,而不是其他列表.