这是基于我的上一个问题 Why am i getting a class cast exception(with generics, comparable)?
这是我的设计。 我有一个抽象的超类,AbstractArrayList,以及两个扩展它的具体子类,排序和未排序的数组列表。
这是AbstractArrayList,它管理实际数据,因为它需要已经实现的方法。
public abstract class AbstractArrayMyList<E> implements MyList<E> {
protected E[] elementData;
.....
}
这是ArrayListSorted的声明,它扩展了AbstractArrayMyList
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)
ArrayListSorted - java line 38在此方法中
public int getIndex(E value) {
....
line 38 - if (value.compareTo(elementData[mid]) < 0) hi = mid - 1;
我从问题中得到的回答澄清了异常是由什么引起的。 当我试着打这个电话时
value.compareTo(elementData[mid]) < 0
值的类型正确,因为extends部分会将类型对象缩小为Comparable类型。但是,运行java字节码的JVM只能将elementData数组识别为对象数组,因此当我尝试将elementData [mid]转换为Comparable时,它实际上并不是Comparable类型。
chrylis在另一个问题中给我的解决方案是在AbstractArrayList中有一个构造函数,它将构造正确的类型化数组
protected AbstractArrayMyList(Class<E> clazz) {
this.elementClass = clazz;
this.elementData = Array.newInstance(clazz, INITIAL_SIZE);
}
我试图在我的排序数组列表子类中使用
调用此构造函数public class ArrayListSorted<E extends Comparable<E>> extends AbstractArrayMyList<E>
public ArrayListSorted() {
super(Class.forName(("E"));
}
...
我从这个帖子得到的语法 - Passing a class as an argument to a method in java
但是我收到编译器错误 - 构造函数AbstractArrayMyList(Class)未定义。 有谁知道这是什么问题?我在AbstractArrayList的问题中定义了chrylis提供给我的相同构造函数,它接受了一个类实例。
答案 0 :(得分:1)
如果您需要参数的具体类,则必须指定它。无法从类型参数E
派生它。
这适用于您的ArrayListSorted()构造函数。如果要保持ArrayListSorted通用(使用类型参数),则只能传递Class
对象。如果您想使其具体,您只需指定参数和类。
在这种情况下,我会使用具体的类名,如:
public class ArrayListSorted<E extends Comparable<E>>
extends AbstractArrayMyList<E> {
public ArrayListSorted(Class<E> cls) {
super(cls);
}
...
public IntArrayListSorted extends ArrayListSorted<Integer> {
public IntArrayListSorted() {
super(Integer.class);
}
...
如您所见,当您指定类型参数(... extends ArrayListSorted<Integer>
)时,它将被定义为Integer,然后构造函数也需要Class<Integer>
:( super(Integer.class)
)。< / p>
一种选择是,使用通用接口作为实现,因此您可以:
public class ArrayListSorted<E extends Comparable<E>> extends AbstractArrayMyList<Comparable>
{
public ArrayListSorted()
{
super(Comparable.class);
}
}
答案 1 :(得分:0)
不,不是字面E
,而是您E
使用的课程。请参阅EnumMap
的构造函数:
new EnumMap<>(KeyEnum.class)
答案 2 :(得分:0)
您收到错误“构造函数AbstractArrayMyList(Class)未定义” 因为你没有这样的构造函数。
public AbstractArrayMyList(Class<E> clazz)
{
elementData=(E[])Array.newInstance(clazz);
}