java - 为什么我会收到类转换异常(使用泛型,可比较)?

标签 java arrays generics interface comparable

我正在尝试实现一个排序和未排序的数组列表。两者都扩展了一个名为 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来自ObjectComparable在您的子类中,该方法的签名最终为 Comparable[]而不是Object[] .

关于java - 为什么我会收到类转换异常(使用泛型,可比较)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28005959/

相关文章:

C# - 我们应该如何在接口(interface)中实现 default(T)?

java - 当有最新数据时更新属性文件

java - 获取 twitter4j 状态时抛出异常?

javascript - 将 JS 文件加载到变量中

arrays - 数组和反转给出相同的结果但不相等

swift - 如何定义一个 Swift 协议(protocol),强制其采用者自己遵守相关类型?

java - AutoCloseable的close方法抛异常有意义吗?这应该如何处理?

java - 将数据从 Activity 发送到 Android 中的 viewpager fragment

c - 循环跳过 C 中的第二个输入

Java抽象方法和接口(interface)