我正在尝试实现一个排序和未排序的数组列表。两者都扩展了一个名为 AbstractArrayMyList 的类,其中包含常见的操作/实现 - toString、clear 等...
这是我的 AbstractArrayMyList 代码(它实现了我定义的通用接口(interface))
public abstract class AbstractArrayMyList<E> implements MyList<E> {
protected E[] elementData;
.....
}
我选择对 elementData 进行保护,以便排序和未排序的专用数组列表可以访问它并对其执行操作。这是我的排序数组列表的声明/代码
public class ArrayListSorted<E extends Comparable<E>> extends AbstractArrayMyList<E>
这一切都编译得很好。但是,当我测试我的代码时,使用这些行
ArrayListSorted<Integer> toTestInteger = new ArrayListSorted<Integer>()
toTestInteger.insert(0);
assertEquals(toTestInteger.get(0).intValue(), 0);
我收到一个类转换异常
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;
异常发生在与compareTo 相同的行上。有谁知道问题是什么?我定义了有界通配符 E extends Comparable,这意味着任何希望使用 ArrayListSorted 的类都必须实现 Comparable 接口(interface)...
我的意思是我什至有正确的语法,来自 http://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html ,类型扩展类/接口(interface)
最佳答案
问题是您使用泛型类型作为数组的类型。数组类型在运行时是具体化的(实际上存在于 JVM 中),但泛型类型却不是。这意味着您的 new E[]
实际上最终成为 Object[]
而不是您想要的类型的数组。
标准集合通过不提供对数组的直接访问并强制转换为 E
来解决此问题。类似 get()
的操作。如果您确实认为使用类型化数组是最佳选择,那么您需要传递 Class<E> clazz
到抽象基类的构造函数并使用它来构造类型正确的数组:
protected AbstractArrayMyList(Class<E> clazz) {
this.elementClass = clazz;
this.elementData = Array.newInstance(clazz, INITIAL_SIZE);
}
您获得 ClassCastException
的原因是编译器用它们的删除替换方法签名,这基本上是可接受类型的最大公分母。既然你正在缩小E
来自Object
至Comparable
在您的子类中,该方法的签名最终为 Comparable[]
而不是Object[]
.
关于java - 为什么我会收到类转换异常(使用泛型,可比较)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28005959/