2013-04-12 15 views
6

Ho riscontrato un problema durante l'esecuzione di un compito per la classe di algoritmi online. Casting Object[] a T[] dove T è paragonabile solleva un'eccezione di run-timeCasting array di oggetti su array di simili

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

potrei riscriverlo in C# che non ha alcun problema con la creazione di array generici ma preferirei imparare a trattare con questo in Giava.

+0

Penso che si dovrebbe vedere http://stackoverflow.com/questions/1817524/generic-arrays-in-java è abbastanza interessante. –

risposta

12

Se stai ricevendo un'eccezione di runtime, significa che gli oggetti che hai provato a trasmettere non hanno questo tipo. La lingua non ha niente a che fare con questo. Probabilmente c'è un bug nel tuo codice.

Modifica: Sembra che tu sia confuso dal funzionamento del sistema di tipi di Java. In C#, i generici rappresentano in realtà diversi tipi in fase di esecuzione. In Java, i tipi generici non esistono in fase di runtime. Sono solo una comodità per consentire una migliore verifica del tipo di tempo di compilazione. Durante la compilazione, i generici vengono sostituiti da un tipo reale in un processo noto come cancellazione dei tipi.

Normalmente, la cancellazione di un tipo generico è Object, ma poiché è stato fornito un limite superiore per T, viene convertito in tale limite, Comparable. Pertanto, dopo la cancellazione, il tuo codice appare come questo.

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

In altre, si sta creando una matrice di tipo Object[] e subito cercando di lanciare per digitare Comparable[]. Poiché Object non implementa Comparable, i tipi non sono compatibili, pertanto si ottiene un'eccezione di runtime. Puoi risolvere questo problema creando invece una serie di Comparable s.

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

Ovviamente c'è un bug e ovviamente ha qualcosa a che fare con il modo in cui Java gestisce i generici. In C# non c'è alcun problema con la creazione di array di parametri di tipo vincolato. – synapse

+0

@synapse Ho modificato la mia risposta per spero che chiarisca le cose per voi. – Antimony

2

Le matrici sono covarianti e questo significa che mantengono il tipo dei loro elementi in fase di runtime. I generici di Java non lo sono. Quindi in pratica non si mescolano.

Consulta anche: Generic arrays in Java

Non è possibile creare array di farmaci generici e non si può lanciare a loro. Meglio usare arraylists.

3

Prova questo:

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

Grazie. Nessuna meraviglia che le FAQ di Java Generics siano lunghe centinaia di pagine. – synapse

+0

C'è un modo molto più semplice per farlo. Vedi la mia risposta. – Antimony

+0

Più semplice ma pericoloso. Puoi anche cambiare il tipo in questo modo: > e verrà compilato ed eseguito anche con il codice originale (dipende dalla firma del metodo mergeSort). Ad esempio, se T è sempre String e cerchi di eseguire String [] aux2 = (String []) aux otterrai un'eccezione. Il tuo array comparabile ha lo stesso problema. Quindi è più semplice ma potrebbe non funzionare sempre. – jdb