为什么我会得到一个类强制转换exception(使用generics,可比较)?

我正在尝试实现一个排序和未排序的数组列表。 两者都扩展了一个名为AbstractArrayMyList的类,它包含常见的操作/实现 – toString,clear等….

这是我的AbstractArrayMyList代码(它实现了我定义的通用接口)

public abstract class AbstractArrayMyList implements MyList { protected E[] elementData; ..... } 

我选择对elementData进行保护,以便排序和未排序的专用数组列表可以访问它并对其执行操作。 这是我的排序数组列表的声明/代码

 public class ArrayListSorted<E extends Comparable> extends AbstractArrayMyList 

这一切都很好。 但是当我用这些行测试我的代码时

 ArrayListSorted toTestInteger = new ArrayListSorted() toTestInteger.insert(0); assertEquals(toTestInteger.get(0).intValue(), 0); 

我得到一个类强制转换exception

 java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable; at myarraylist.ArrayListSorted.getIndex(ArrayListSorted.java:38) 

发生在这里

 @Override public int getIndex(E value) { int lo = 0; int hi = size; while (lo <= hi) { // Key is in a[lo..hi] or not present. int mid = lo + (hi - lo) / 2; if (value.compareTo(elementData[mid]) < 0) hi = mid - 1; 

该exception发生在与compareTo相同的行上。 有谁知道这是什么问题? 我定义了有界通配符,E扩展了Comparable,这意味着任何希望使用ArrayListSorted的类都必须实现Comparable接口…

我的意思是我甚至有正确的语法,来自http://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html ,输入extends class / interface

问题是您使用generics类型作为数组的类型。 数组类型在运行时被实现(实际存在于JVM中),但generics类型不是。 这意味着您的new E[]实际上最终成为Object[]而不是您想要的类型的数组。

标准集合通过不提供对数组的直接访问并在get()类的操作上转换为E来解决此问题。 如果您真的认为使用类型化数组是最佳选择,那么您需要将Class clazz传递给抽象基类的构造函数,并使用它来构造正确类型的数组:

 protected AbstractArrayMyList(Class clazz) { this.elementClass = clazz; this.elementData = Array.newInstance(clazz, INITIAL_SIZE); } 

你得到ClassCastException的原因是编译器用它们的擦除替换方法签名,这基本上是可接受类型的最大公分母。 由于您在子类中将EObject缩小为Comparable ,因此该方法上的签名最终为Comparable[]而不是Object[]