2012-03-31 134 views
0

所以 - 我想使泛型列表的二維數組包含一些數據我感興趣的(對某些設定尺寸的網格),製作泛型列表的二維數組在Java中

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警告。很好奇爲什麼這不是類型安全的,我可以做些什麼來使它安全(缺少使用二維數組)。我明白,混合數組和泛型不是很好,但在這種情況下,我只是寫這個來運行一些實驗,所以我使用它而不是列表列表來列出清單列表來節省我一些時間。還有沒有其他更優雅的方法可以讓我輕鬆讀/寫語法(即沒有嵌套列表),但也是類型安全的?

謝謝!

+2

@assylias:因爲不編譯。差遠了。泛型和數組在Java中不能像那樣工作。 – 2012-03-31 19:49:55

回答

2

唯一的類型安全選項是使用嵌套列表。

因爲類型擦除,你不能做new ArrayList<MyDataStruct>[w][h],因爲基本上成爲new ArrayList[w][h] ...,事情變得複雜和多毛的,快速的,因爲數組的行爲很像仿製藥。

Java認爲String[]Object[]的子類,但ArrayList<String>不是ArrayList<Object>的子類。通常,當您嘗試將元素放入與陣列的真實類型不匹配的數組中時,陣列會拋出一個ArrayStoreException,但由於類型擦除,當泛型出現在圖片中時,它不能這樣做。

喬希布洛赫給出了有效的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語言完全合法的唯一途徑是禁止通用陣列創建,或至少將其標記爲不安全。

這就是說,國際海事組織,輸入List並與通用名單進行適度的開銷是絕對值得的類型安全。

+0

所以我想只要我使用數組,我會被卡在警告中?這是「安全」的,因爲我知道我應該放棄什麼並擺脫它。但tbh,我什至不能想到我的代碼將是類型不安全的情況(所以你的意思是,如果我決定把一個列表放在我的2d數組中,而不是泛型類型MyDataStruct,Java將無法計算出這個出來嗎?)。 – sksw 2012-03-31 19:55:50

+0

或多或少正確。如果有幫助,我添加了Josh Bloch的Effective Java的一個例子。 – 2012-03-31 21:36:36

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]