当前位置: 首页 > 面试题库 >

为什么我会收到类强制转换异常(具有泛型,具有可比性)?

秦雅逸
2023-03-14
问题内容

我试图实现一个排序和未排序的数组列表。两者都扩展了一个名为AbstractArrayMyList的类,其中包含常见的操作/实现-
toString,clear等。

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

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扩展Comparable,这意味着希望与ArrayListSorted一起使用的任何类都必须实现Comparable接口。

我的意思是我什至拥有正确的语法,来自http://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html,类型扩展了类/接口


问题答案:

问题是您将泛型类型用作数组的类型。在运行时对数组类型进行了 修饰 (实际上存在于JVM中),但没有对通用类型进行修饰。这意味着您new E[]实际上最终将成为Object[]所需类型的数组,而不是该数组。

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

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

您得到的原因ClassCastException是,编译器将其签名替换为擦除,这基本上是可接受类型的最大公分母。由于您要缩小子类中的EObjectComparable,因此该方法上的签名最终被Comparable[]代替Object[]



 类似资料:
  • 我试图实现一个排序和未排序的数组列表。两者都扩展了一个名为AbstractArrayMyList的类,该类包含常见的操作/实现——toString、clear等。。。。 下面是我的AbstractArrayMyList代码(它实现了我定义的通用接口) 我选择对elementData进行保护,以便排序和未排序的专用数组列表可以访问并对其执行操作。这是我对排序数组列表的声明/代码 这一切都很好。然而,

  • 因此,我遵循本教程,我有一个带有GridLayoutManager实现的RecycerView。GridLayoutManager有2列。我希望有两个视图类型,所以我使用了两个扩展RecycerView.Viewholder的Viewholder,并且重写了这个方法:getItemViewType(int位置),但是我使用了一个强制转换异常。Logcat显示以下内容: java.lang.Clas

  • 问题内容: 还有其他一些SO问题在讨论可以使用Eclipse的编译器而不是javac进行泛型编译的问题(即Java:泛型在Eclipse和javac中处理不同,而泛型可以在Eclipse中编译和运行,但不能在javac中编译)-但这看起来就像一个稍微不同的人。 我有一堂课: 我还有一个带有方法的类,该方法接受来自以下类型的任意对象: 这在Eclipse中可以正常工作,但是当我使用进行了干净的构建时

  • 我试图在一个方法中使用泛型,在这个方法中,我将一个json反序列化为pojo,这样它就可以返回任何对象类型。 这里我的代码: 问题是

  • 我在这里遇到了一个关于带列表的泛型有界类型的小问题。请帮帮我! 有什么方法可以克服这个问题,或者我可以安全地压制警告吗?

  • 我在覆盖接口中声明的方法时遇到了一些问题,该方法使用泛型参数作为其异常,并使用泛型作为其参数之一。为了说明,我编写了以下代码接口 通过javac运行,我得到 请注意,在接口中,metodoA和metodoB之间的唯一区别在于它们的参数。 为什么Implementadora(Implementadora)的metodoB(metodoB)(代码)不重写Interfaz(代码),但重写metodoB(