当泛型类型实现接口时,不能将对象数组强制转换为泛型类型数组

fdbelqdn  于 2021-07-12  发布在  Java
关注(0)|答案(3)|浏览(338)

我正在用java实现一个快速排序类。为了排序工作,要排序的项需要具有可比性,例如通过实现 Comparable 接口。然而,实施 Comparable 在运行时在返回数组切片的方法中强制转换时出现问题:

public class QuickSorter<T extends Comparable<T>> {

    ...

    private T[] sliceOfArray(T[] arr, int start, int end) {
        Object[] slice = new Object[end - start];

        for (int i = start; i < end; i++) {
            slice[i] = arr[i];
        }

        return (T[]) slice; // Throws exception at runtime.
    }
}

例外情况是:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
    at com.sortingalgos.QuickSorter.sliceOfArray(QuickSorter.java:55)
    at com.sortingalgos.QuickSorter.sort(QuickSorter.java:11)
    at com.sortingalgos.MainApp.main(MainApp.java:11)

我怎么才能避开这个?

daupos2t

daupos2t1#

简单的解决办法是改变这条线

Object[] slice = new Object[end - start];

Comparable[] slice = new Comparable[end - start];

铸造业 T[] 是个黑客。它实际上并没有改变数组的类型。你不想把它传来传去,假装它真的是正确键入的。使用起来可能更清楚 Object[] (或 Comparable[] )或者只是老样子 List<T> .

v8wbuo2f

v8wbuo2f2#

您甚至不能执行以下操作:

Object[] a = new Object[] {1,3,4,5};
        Integer[] b = (Integer[])a;
        System.out.println(Arrays.toString(b));

这是因为不能保证 Object[] a 看起来不像是这样的:

Object[] a = new Object[]{1,3,4,5.7}

这显然不是一个整数数组。但你可以这么做。

Object[] a = new Integer[] {1,3,4,5};
        Integer[] b = (Integer[])a;
        System.out.println(Arrays.toString(b));
5cnsuln7

5cnsuln73#

问题是 Object 不是一个数组 Comparable . 你需要 slice 数组的元素类型与 arr 数组。你可以通过改变

Object[] slice = new Object[end - start];

T[] slice = java.lang.reflect.Array.newInstance(arr.class.getComponentType(), end - start);

换句话说,在运行时使用反射来确定元素类型,并创建相同类型的切片数组。
然而,使用反射可能性能较差。对于像quicksort这样的就地排序算法,您根本不需要创建任何新的数组,只需使用输入数组即可(或者克隆它,如果不允许修改输入。)

相关问题