繁体   English   中英

泛型类型实现接口时,无法将 Object 数组强制转换为泛型类型数组

[英]Can't cast array of Object to array of generic type when generic type implements interface

我正在用 Java 实现一个 Quicksort 类。 为了使排序起作用,要排序的项目需要具有可比性,例如通过实现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)

我怎样才能解决这个问题?

简单的解决方法是改变这一行

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

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

转换为T[]的业务是一种黑客行为。 它实际上并没有改变数组的类型。 您不想假装它确实输入正确而传递它。 使用Object[] (或Comparable[] )或简单的旧List<T>可能更清楚。

您甚至无法执行以下操作:

        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));


问题是Object数组不是Comparable数组。 您需要slice数组与arr数组具有相同的元素类型。 你可以通过改变来实现这一点

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

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

换句话说,使用反射在运行时确定元素类型,并创建相同类型的切片数组。

然而,使用反射的性能可能较低。 对于像 QuickSort 这样的就地排序算法,您根本不需要创建任何新数组,您可以只使用输入数组。 (或者克隆它,如果你不允许修改输入。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM