java - 为什么我会得到一个类转换异常?

标签 java arrays list generics arraylist

我有两个类,AbstractArrayMyList 类和 ArrayListSorted 类,它扩展了 AbstractArrayMyList。

这是我对 AbstractArrayMyList 和相关构造函数的声明

public abstract class AbstractArrayMyList<E extends Comparable<E>> implements MyList<E>  {
    private static final int DEFAULT_CAPACITY = 100; 
    protected E[] elementData;
    public AbstractArrayMyList() {
            this( DEFAULT_CAPACITY);
    }
    public AbstractArrayMyList( int capacity) {
           elementData = (E[]) new Object[capacity];
    }

MyList 是 adt 接口(interface)

还有我的 ArrayListSorted 类(带有相关的构造函数),

 public class ArrayListSorted<E extends Comparable<E>> extends 
       AbstractArrayMyList<E> {
       public ArrayListSorted() {
              super();
        }
}

这是导致类转换异常的代码行。 (只是创建一个数组列表排序类,具有有界整数类型。我真的很困惑为什么会发生这个异常。

ArrayListSorted<Integer> toTestInteger = new ArrayListSorted<Integer>();

chrylis 从这里解释,Why am i getting a class cast exception(with generics, comparable)?问题是 jvm 将我的 new Object[capacity] 视为对象数组。我同意这一点,但那时我的 AbstractArrayMyList 的定义仍然是

public abstract class AbstractArrayMyList<E> implements MyList<E>   

,这意味着 jvm 必须将 E 视为对象,因为它对它一无所知。但是既然我添加了 E extends Comparable 难道不应该允许这种转换吗? JVM 会将其识别为可比较对象的数组?

最佳答案

问题是对象不可比较。因此在抽象类的构造函数中创建数组失败。

您可以通过删除抽象声明中的 Comparable 部分来解决此问题:

 public abstract class AbstractArrayMyList<E> implements MyList<E>  {
   ...

}

然后在你的子类中:

public class ArrayListSorted<E extends Comparable<E>> extends AbstractArrayMyList<E> {
    ...
}

让一切正常。没有类转换异常。

无论如何,这最终会变得更好,因为之前您会将 AbstractArrayMyList 的所有子类限制为 Comparable。现在不必了。

更新

我现在明白您将对抽象类中的元素求助。在这种情况下,使您的数组类型为 Comparable:

public abstract class AbstractArrayMyList<E extends Comparable<E>> implements List<E>  {

    ...

    public AbstractArrayMyList( int capacity) {
         elementData = (E[]) new Comparable[capacity];
   }

   ...

那么你所有的排序都会起作用:

例如有一个主要的方法:

public static void main(String... args){
    ArrayListSorted<Integer> toTestInteger = new ArrayListSorted<Integer>();

    toTestInteger.add(5);
    toTestInteger.add(2);
    System.out.println(toTestInteger.get(0));
    System.out.println(toTestInteger.get(1));

将正确打印

2
5

(这假设您的抽象类中的 add() 代码求助于数组)

更新 2

如果您在子类中进行排序,那么您将对抽象类进行一些小的更改。

完成这项工作的最简单方法是让抽象类通过构造函数获取传入的数组。这样,子类生成数组类型。

public abstract class AbstractArrayMyList<E> implements List<E>  {
    protected E[] elementData;
    int size=0;

    protected AbstractArrayMyList(E[] elementData) {
         this.elementData = elementData;
    }

    ....

 }

然后在您的子类中,您执行默认容量操作,然后调用父类的构造函数,传入您已构造的正确类型的数组。

public class ArrayListSorted<E extends Comparable<E>> extends AbstractArrayMyList<E> {
     private static final int DEFAULT_CAPACITY = 100; 

     public ArrayListSorted(){
         this(DEFAULT_CAPACITY);
     }

     @SuppressWarnings("unchecked")
    public ArrayListSorted(int initialSize){
           //call parent constructor passing in new array
        super((E[]) new Comparable[initialSize]);
    }

...

现在代码又可以正常工作了

关于java - 为什么我会得到一个类转换异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28018100/

相关文章:

java - JUNIT - 断言异常

java - Java方法描述符中美元符号的含义?

java - 在简单的 JXTA 2.7 应用程序中获取异常

php - 反转 PHP file() 函数

python - 如何拆分列表并将其打印在不同的行中?

java - 尽管移动工作区,Eclipse "bundle org.eclipse.core.resources is invalid"启动时崩溃

Javascript:找出数组中是否至少有两个不同的值

c - c 中具有多维数据类型的多维数组

html - 为什么在 CSS 中不显示 :inline work for "li a {", 而只显示 "li {"?

r - 将列表逐元素附加到 R 中嵌套列表的元素