Ljava.lang.Object; 无法转换为[Ljava.lang.Integer
我写了一个generics类,下面是类的构造函数。 我想做这样的事情,就像写在线一样
elements = (E[])new Object[size]
因为我不知道运行时的generics类型因此会抛出exception。
public class Stack implements IStack { protected E[] elements = null; protected int top = -1; protected int size= 0; private static final int DEFAULT_CAPACITY = 10; public Stack(){ this(DEFAULT_CAPACITY); } public Stack(int size){ if(size <0){ throw new IllegalArgumentException("Initial capacity cannot be negative or zero"); } ArrayList ar = new ArrayList(); elements = (E[])new Object[size]; } }
有什么方法可以解决这些问题吗? E的声明是
protected E[] elements = null;
这就是我试图打电话的方式
Random ran = new Random(); Stack st = new Stack(); st.push(ran.nextInt(100));
更新伙计们,感谢您的帮助。 我正在搞乱generics,所以问题正在形成。 以下是创建问题的所有代码 –
public class StackMain { public static void main(String[] args) { MinMaxStack minMaxStack = new MinMaxStack(); Random ran = new Random(); for (int k = 0; k < 10; k++) { minMaxStack.push(ran.nextInt(100)); } System.out.println(minMaxStack); } } public class MinMaxStack extends Stack implements IMinMaxStack{ private int min; private int max; /* * Approach 1: * For push method we can push and update the minimum/maximum value * For pop method we will be traversing whole stack to find out the new minimum/maximum * */ @Override public void push(Integer element){ if(isEmpty()){ this.min = element; this.max = element; elements[top+1] = element; size++; }else{ if(element max){ max = element; } elements[top+1] = element; size++; } } } public class Stack implements IStack { protected E[] elements = null; protected int top = -1; protected int size= 0; private static final int DEFAULT_CAPACITY = 10; public Stack(){ this(DEFAULT_CAPACITY); } public Stack(int size){ if(size <0){ throw new IllegalArgumentException("Initial capacity cannot be negative or zero"); } elements = (E[])new Object[size]; } public void push(E element) { ensureCapacity(); elements[top+1] = element; size++; } } public interface IStack { public void push(E element ); } public interface IMinMaxStack extends IStack { public int min(); public int max(); }
更新2 :看起来,除了传递下面的答案中提到的类类型,我们无法做到这一点。
这是重现exception所需的最小代码。
class Stack { protected E[] elements = (E[])new Object[1]; } class IntStack extends Stack { void push(Integer i) { // subtly accessing elements as Integer[] which it's not elements[0] = i; } }
Javagenerics是使用类型擦除实现的,因此在编译之后,此代码转换为如下所示:
class Stack { protected Object[] elements = new Object[1]; } class IntStack extends Stack { void push(Integer i) { // throws ClassCastException ((Integer[])elements)[0] = i; } }
显然, new Object[]
不是Integer[]
。 注意演员如何移动到你没有明确表达的地方。 这就是为什么(E[])new Object[size]
是未经检查的强制转换并显示警告的原因。
相反,您应该使用Object[]
并仅在需要将元素返回到外部世界时执行未经检查的强制转换。
class Stack { private Object[] elements; private int size; Stack(int len) { elements = new Object[len]; } void push(E e) { elements[size] = e; size++; } E pop() { @SuppressWarnings("unchecked"); E e = (E)elements[size - 1]; size--; return e; } }
基本上,当你做(E[])new Object[size]
,这是一个谎言。 对象的实际运行时类是Object[]
,它不是E[]
的子类型,无论E
是什么(除非E
是Object
)。 因此,演员在理论上是不正确的。 但是,这不会立即产生任何问题,因为在Stack
类中, E
被擦除到其上限,在本例中为Object
。 所以在Stack
类中,我们可以使用elements
作为E[]
,并将E
放入并从中获取E
,没有问题。
只有当elements
类型为E[]
的(不正确的)事实被“暴露”到类的外部(在E
的擦除范围之外)到某个范围内,其中有人具有E
的具体类型参数时,才会出现问题。 。 这通常发生在有人无意中使elements
公开,或实现一个将其返回到外部的方法时
E[] getElements() { return elements; }
然后在类的外部,有人有一个Stack
,并调用此方法,并期望SomeSpecificType[]
,这不是它得到的。
但是,您的Stack
类没有这样的方法。 那你怎么“暴露” elements
? 答案是elements
protected
,因此“暴露”到子类。 在这种情况下,子类MinMaxStack
使用E
的特定类型扩展Stack
,因此,它将elements
“视为”特定类型的数组,而不是。
我相信通常的方法是将Class
传递给构造函数,并使用Array.newInstance(Class>, int...)
类的
public Stack(Class cls, int size){ if(size <0){ throw new IllegalArgumentException("Initial capacity cannot be " + "negative or zero"); } elements = (E[]) Array.newInstance(cls, size); }
编辑
从您的更新, 请不要使用原始类型 。 使用Java 7及更高版本,您可以使用菱形运算符<>
Stack st = new Stack<>(); st.push(ran.nextInt(100));
对于早期版本,您可以指定generics类型
Stack st = new Stack (); st.push(ran.nextInt(100));
现在很清楚了。 您正在尝试创建没有generics类型的Stack
。 考虑Stack
代替。
以下是修复它的方法,你不应该做(T[]) new Object[DEFAULT_CAPACITY];
相反,抽象应该存在例如(T[]) new Comparable[DEFAULT_CAPACITY];
public class ArrayStack> implements Stack { private final int DEFAULT_CAPACITY = 50; private int top; private T[] elements; @SuppressWarnings("unchecked") public ArrayStack() { this.elements = (T[]) new Comparable[DEFAULT_CAPACITY]; this.top = 0; } }