所以 - 我想创建一个包含我感兴趣的一些数据的通用列表的二维数组(在一些设置大小的网格上),
private ArrayList<MyDataStruct>[][] gridData;
当我初始化这个数组时,我去了,
gridData = (ArrayList<MyDataStruct>[][])new ArrayList[w][h];
for(int x=0; x<w; x++)
for(int y=0; y<h; y++){
gridData[x][y] = (ArrayList<MyDataStruct>)new ArrayList<MyDataStruct>(0);
//other stuff, i.e. get data from somewhere, etc
}
我收到unchecked cast
警告。很好奇为什么这不是类型安全的,我可以做些什么使其类型安全(没有切换使用2d阵列)。我知道混合数组和泛型并不是很好,但在这种情况下我只是写这个来运行一些实验,所以我使用它而不是列出列表列表以节省一些时间。有没有其他更优雅的方法让我能够轻松读取/写入语法(即没有嵌套列表),但也是类型安全的?
谢谢!
答案 0 :(得分:2)
唯一的类型安全选项是使用嵌套列表。
由于类型擦除,你不能new ArrayList<MyDataStruct>[w][h]
,因为它基本上变成new ArrayList[w][h]
...而且事情变得复杂多毛,快,因为数组不1 em>表现得像泛型。
Java认为String[]
是Object[]
的子类,但ArrayList<String>
不是ArrayList<Object>
的子类。通常,当您尝试将元素放入与数组的真实类型不匹配的数组时,数组会抛出ArrayStoreException
,但由于类型擦除,当泛型出现在图片中时,它不能这样做。 / p>
Josh Bloch在Effective Java中给出了以下示例:
// Why generic array creation is illegal - won't compile!
List<String>[] stringLists = new List<String>[1];
List<Integer> intList = Arrays.asList(42);
Object[] objects = stringLists;
objects[0] = intList;
String s = stringLists[0].get(0);
防止所有这些代码在Java中完全合法的唯一方法是禁止创建通用数组,或者至少将其标记为不安全。
也就是说,IMO,键入List
并使用通用列表进行操作的适度开销绝对值得类型安全。
答案 1 :(得分:0)
我遇到了同样的问题(只是一些实验,“完成任务”的方法)。 这是一个似乎对我有用的解决方案,使用反射。
请注意,它与数组中的单元格类型(可以是列表,地图,任何内容)100%无关。也许还有一点点工作,它也可以与阵列的尺寸相关,但我今天要炒更大的鱼......
private static <T> T[][] makeArray(Class<T> componentType, int... dimentions) {
return (T[][]) Array.newInstance(componentType, dimentions);
}
下面附带的是一种测试方法。保持数组的类型通用我不得不在这里丑陋。这可以在另一个包装方法中处理,以保持客户端代码的良好和干净:
@Test
public void testMakeArray() throws Exception {
@SuppressWarnings("unchecked")
List<String>[][] arr = makeArray(List.class, 2, 3);
Assert.assertEquals(2, arr.length);
Assert.assertEquals(3, arr[0].length);
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
arr[i][j] = Arrays.asList("cell", "r="+i, "c="+j);
System.out.print(arr[i][j] + "\t");
}
System.out.println("");
}
}
打印:
[cell, r=0, c=0] [cell, r=0, c=1] [cell, r=0, c=2]
[cell, r=1, c=0] [cell, r=1, c=1] [cell, r=1, c=2]