2013-04-12 40 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