2013-04-12 66 views
6

我在爲在線算法類做功課時遇到了問題。鑄造Object[]T[]其中T是可比產生運行時異常將對象數組轉換爲可比較的數組

public static <T extends Comparable<? super T>> void mergeSort(T[] xs) { 
    T[] aux = (T[]) new Object[xs.length]; 
    mergeSort(xs, aux, 0, xs.length); 
} 

我可以重寫它在C#中不具有與創建通用陣列的任何問題,但我寧願學習如何處理這個Java的。

+0

我想你應該看到http://stackoverflow.com/questions/1817524/generic-arrays-in-java 這是相當有趣的。 –

回答

12

如果您得到一個運行時異常,這意味着您嘗試投射的對象不會實際使用該類型。語言與它沒有任何關係。您的代碼中可能存在一個錯誤。

編輯:聽起來好像你對Java的類型系統的工作方式感到困惑。在C#中,泛型實際上在運行時表示不同的類型。在Java中,泛型類型在運行時不存在。它們只是一個方便,可以更好地編譯時間類型檢查。在編譯過程中,泛型在被稱爲類型擦除的過程中被實際類型所取代。

通常,刪除一個通用類型爲Object,但由於您提供了T的上限,因此將其轉換爲該綁定的Comparable。因此,擦除後,你的代碼看起來像這樣。

Comparable[] aux = (Comparable[]) new Object[xs.length]; 

。換句話說,你要創建Object[]類型的數組,並立即試圖將它轉換爲類型Comparable[]。由於Object沒有實現Comparable,這些類型是不兼容的,所以你得到一個運行時異常。您可以通過創建一個Comparable的數組來解決此問題。

public static <T extends Comparable<? super T>> void mergeSort(T[] xs) { 
    T[] aux = (T[]) new Comparable[xs.length]; 
    mergeSort(xs, aux, 0, xs.length); 
} 
+0

顯然有一個錯誤,顯然它與Java處理泛型的方式有關。在C#中,創建約束類型參數數組沒有問題。 – synapse

+0

@synapse我已經編輯了我的答案,希望能爲你澄清事情。 – Antimony

2

數組是協變的,這意味着它們在運行時保留其元素的類型。 Java的泛型不是。所以基本上他們不混合。

參見:Generic arrays in Java

不能創建泛型的數組,你可以不投給他們。最好使用數組列表。

3

試試這個:

public static <T extends Comparable<? super T>> void mergeSort(T[] xs) { 
    T[] aux = (T[])java.lang.reflect.Array.newInstance(xs.getClass().getComponentType(), xs.length); 
    mergeSort(xs, aux, 0, xs.length); 
} 
+0

謝謝。難怪Java泛型常見問題解答長達數百頁。 – synapse

+0

有一個更簡單的方法來做到這一點。看到我的答案。 – Antimony

+0

更簡單但危險。你也可以像這樣改變它的類型:>,即使使用原始代碼(取決於mergeSort方法的簽名)它也會編譯和運行。但是,例如,如果T始終是String,並且您嘗試執行String [] aux2 =(String [])aux,您將得到一個異常。您的Comparable數組具有相同的問題。所以它更簡單,但它可能無法一直工作。 – jdb