有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我正在用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)

我怎样才能避开这件事


共 (3) 个答案

  1. # 1 楼答案

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

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

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

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

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

  2. # 2 楼答案

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

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

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

    T[]投球的生意是一种恶作剧。它实际上并没有改变数组的类型。你不想把它到处传来传去,假装它确实是正确键入的。使用Object[](或Comparable[])或简单的旧List<T>可能更清楚

  3. # 3 楼答案

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

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