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