大家好,我该怎么做才能初始化
ArrayList<Record<T>> [] values;
有许多行和列?例如,三行四列?
使用泛型类型的数组(例如ArrayList<T>
)是一种通向地狱的方式。以下行甚至没有编译:
ArrayList<Record<T>>[] values = new ArrayList<Record<T>>[SIZE_ARRAY];
编译器发出此错误:
Cannot create a generic array of ArrayList<Record<T>>
唯一明智的解决方案是创建一个列表列表:
// create matrix
ArrayList<ArrayList<Record<T>>> matrix = new ArrayList<ArrayList<Record<T>>>();
// add 3 rows:
for (int i = 0; i < 3; i++) {
ArrayList<Record<T>> row = new ArrayList<Record<T>>();
matrix.add(row);
// add 4 elements to each row
for (int j = 0; j < 4; j++) {
Record<T> record = ... // get the record
row.add(record);
}
}
现在您可以访问 [2][3] 处的元素(最后一行的最后一个元素):
Record<T> record = matrix.get(2).get(3);
做就是了:
ArrayList<Record<T>>[] values = (ArrayList<Record<T>>[])new ArrayList<?>[SIZE_ARRAY];
会有一个未经检查的演员表警告,你基本上可以忽略。
不允许创建参数化类型的数组的真正原因有点深奥。Java 中的数组(与泛型集合不同)具有(并且一直具有)在运行时检查它们的特性——即每次将元素放入其中时,它都会检查该元素是否是数组组件类型的实例(其中它在运行时知道)。如果不是,它会引发异常 (ArrayStoreException)。
现在,考虑参数化类型的数组。鉴于您知道数组的上述行为,您会期望参数化类型的数组会检查放入其中的东西是否是该参数化类型的实例。除了在 Java 中不可能在ArrayList<Something>
运行时检查某事物是否是参数化类型 ( ) 的实例。您最多可以检查它是一个ArrayList
,而不是它的参数。
由于它不会完全符合人们的期望,Java 设计者决定完全禁止创建参数化类型的数组。您仍然可以创建原始类型的数组(例如new ArrayList[5]
)或通配符类型的数组(例如new ArrayList<?>[5]
),因为在这些情况下,可以在运行时检查对象是否是实例(即obj instanceof ArrayList
并且obj instanceof ArrayList<?>
是合法的,但obj instanceof ArrayList<Something>
不是)。(他们还可以创建一个特殊情况,即参数化类型的数组只检查原始类型的元素,而不是参数化类型,但这会造成不一致。)但是,可能大多数遇到这个问题的人都没有考虑过这种能力的数组在运行时检查它们的元素类型——他们可能只是想创建一个正常使用的数组。
您还可以将数组转换回参数化类型的数组类型。这是一个未经检查的强制转换,因为如上所述,参数化类型的数组无法满足数组的约定来完全检查其元素类型——例如,现在如果你有一个ArrayList<String>[]
,就ArrayList<Integer>
可以添加一个到数组而不产生异常。然而,99% 的人并不关心这个功能,未经检查的演员说,嘿,我们知道这个限制,但无论如何我们都想做。