Java 1.6:创建列表数组<;T>;

Java 1.6:创建列表数组<;T>;,java,generics,Java,Generics,为什么我不能创建一个列表数组 List<String>[] nav = new List<String>[] { new ArrayList<String>() }; Eclipse说List和ArrayList是原始类型,但它编译 看起来很简单,为什么不起作用呢?一般来说,您不能创建泛型类型的数组 原因是JVM无法检查是否只将正确的对象放入其中(ArrayStoreException除外),因为运行时不存在List和List之间的差异 当然,您可以通过使用

为什么我不能创建一个列表数组

List<String>[] nav = new List<String>[] { new ArrayList<String>() };
Eclipse说List和ArrayList是原始类型,但它编译


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

一般来说,您不能创建泛型类型的数组

原因是JVM无法检查是否只将正确的对象放入其中(ArrayStoreException除外),因为运行时不存在
List
List
之间的差异

当然,您可以通过使用原始类型
List
或未绑定的通配符类型
List
来欺骗编译器,然后将其强制转换为
List
。但是你有责任只把
列表
放进去,而不把其他列表放进去。

好吧,回答你的问题

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

这是 当然,这很烦人。这一限制 有必要避免以下情况:

// 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);
//实际上不允许。
列表[]lsa=新列表[10];
对象o=lsa;
对象[]oa=(对象[])o;
List li=new ArrayList();
加(新整数(3));
//不可靠,但通过运行时存储检查
oa[1]=li;
//运行时错误:ClassCastException。
字符串s=lsa[1]。获取(0);

如果参数化类型的数组是 如果允许,前面的示例将 编译时没有任何未选中项 警告,但在运行时失败。 我们已经把类型安全作为首要任务 泛型的设计目标


没有确切的答案,但有一个提示:

最后一个示例有一个原始类型警告,因为您忽略了列表的类型化;通常,更好的(类型安全)方法是指定列表中包含哪些对象类型,您在前面的示例中已经这样做了(
list
,而不是
list

使用数组不是最佳实践,因为它们的使用大多数时候都包含错误;使用集合类(列表、集合、映射等)可以使用打字和方便的方法来处理其内容;只需看看Collections类的静态方法


因此,只需使用前面答案的示例

另一种解决方案是扩展
LinkedList
(或
ArrayList
等),然后创建子类的数组

private static class StringList extends LinkedList<String> {}

public static void main(String[] args)
{
    StringList[] strings = new StringList[2];
    strings[0] = new StringList();
    strings[1] = new StringList();
    strings[0].add("Test 1");
    strings[0].add("Test 2");
    strings[1].add("Test 3");
    strings[1].add("Test 4");
    System.out.println(strings[0]);
    System.out.println(strings[1]);
}
私有静态类StringList扩展LinkedList{}
公共静态void main(字符串[]args)
{
StringList[]字符串=新的StringList[2];
字符串[0]=新的StringList();
strings[1]=新的StringList();
字符串[0]。添加(“测试1”);
字符串[0]。添加(“测试2”);
字符串[1]。添加(“测试3”);
字符串[1]。添加(“测试4”);
System.out.println(字符串[0]);
System.out.println(字符串[1]);
}

可以复制,但这违背了泛型的目的。“如果允许参数化类型的数组,上面的示例将在编译时没有任何未检查的警告,但在运行时失败。”这不是原因<代码>对象[]sa=新字符串[10];oa[1]=新整数(3)还将“编译时没有任何未检查的警告,但在运行时失败”。更重要的一点是,它应该在存储时失败,并出现ArrayStoreException(因此数组是运行时检查的)。但是运行时检查不能检查泛型,这就是为什么不允许创建参数化类型的数组。但是不能创建
列表的数组
——这就是问题的关键(也是使用上一个示例的原因)。
List[] getLists() {
    return new List[] { new ArrayList(), new ArrayList() };
}
// 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);
private static class StringList extends LinkedList<String> {}

public static void main(String[] args)
{
    StringList[] strings = new StringList[2];
    strings[0] = new StringList();
    strings[1] = new StringList();
    strings[0].add("Test 1");
    strings[0].add("Test 2");
    strings[1].add("Test 3");
    strings[1].add("Test 4");
    System.out.println(strings[0]);
    System.out.println(strings[1]);
}