7

我在做在线算法课的作业时遇到了一个问题。转换Object[]T[]T 是 Comparable 的位置会引发运行时异常

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 中处理这个问题。

4

3 回答 3

12

如果您遇到运行时异常,则意味着您尝试转换的对象实际上并不具有该类型。语言与它没有任何关系。您的代码中可能存在错误。

编辑:听起来您对 Java 类型系统的工作方式感到困惑。在 C# 中,泛型实际上在运行时表示不同的类型。在 Java 中,泛型类型在运行时不存在。它们只是为了方便实现更好的编译时类型检查。在编译期间,泛型在称为类型擦除的过程中被实际类型替换。

通常,泛型类型的擦除是Object,但由于您为 提供了上限T,它会转换为该范围,Comparable。因此,擦除后,您的代码如下所示。

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

换句话说,您正在创建一个 type 数组Object[]并立即尝试将其强制转换为 type Comparable[]。由于Object未实现Comparable,因此类型不兼容,因此您会遇到运行时异常。您可以通过创建一个 s 数组来解决此问题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);
}
于 2013-04-12T21:45:29.983 回答
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);
}
于 2013-04-12T21:54:51.587 回答
2

数组是协变的,这意味着它们在运行时保留其元素的类型。Java 的泛型不是。所以基本上它们不会混合。

另请参阅:Java 中的通用数组

您不能创建泛型数组,也不能强制转换为它们。最好使用数组列表。

于 2013-04-12T21:46:53.923 回答