[英]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.