java Ljava.lang.Object; 不能转换为 [Ljava.lang.Integer

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27591061/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 12:04:40  来源:igfitidea点击:

Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer

javagenerics

提问by Avneesh

I have written a generic class and below is the constructor of the class. I want to do something like this as written in line

我写了一个泛型类,下面是该类的构造函数。我想做这样的事情

elements = (E[])new Object[size] 

Because I do not know the generic type on the run time therefore it will throw an exception.

因为我不知道运行时的泛型类型,所以它会抛出异常。

public class Stack<E> implements IStack<E> {
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<Integer> ar = new ArrayList<Integer>();
    elements = (E[])new Object[size];
}
}

Is there any way to solve such problems? The declaration of E is

有没有办法解决此类问题?E 的声明是

protected E[] elements = null;    

This is how I am trying to call

这就是我试图打电话的方式

Random ran = new Random();
Stack<Integer> st = new Stack<Integer>();
st.push(ran.nextInt(100));

UpdateGuys, Thanks for the help. I was messing around with generics so the problem was being created. Here is all the code which created the problem -

更新伙计们,感谢您的帮助。我在搞泛型,所以问题就产生了。这是造成问题的所有代码 -

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<Integer> implements IMinMaxStack<Integer>{

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 < min){
            min = element;
        }
        if(element > max){
            max = element;
        }
        elements[top+1] = element;
        size++;
    }
}
}

public  class Stack<E> implements IStack<E> {
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<E> {    
public void push(E element );
}


public interface IMinMaxStack<E> extends IStack<E> {    
public int min();   
public int max();   
}

Update 2: Seems, other than passing the class type as mentioned in an answer below, there is no way we can do this.

更新 2:似乎,除了传递下面答案中提到的类类型之外,我们无法做到这一点。

回答by newacct

Basically, when you do (E[])new Object[size], it is a lie. The object's actual runtime class is Object[], which is not a subtype of E[]for whatever Eis (unless Eis Object). So the cast is, theoretically, incorrect. However, this does not create any immediate problems because inside the Stackclass, Eis erased to its upper bound, in this case Object. So inside the Stackclass, we can use elementsas E[], and put Ein and get Eout of it, with no problem.

基本上,当你这样做时(E[])new Object[size],这是一个谎言。对象的实际运行时类是Object[],它不是E[]任何东西的子类型E(除非EObject)。因此,从理论上讲,演员阵容是不正确的。但是,这不会立即产生任何问题,因为在Stack类内部,E被擦除到其上限,在本例中为Object。所以在Stack类内部,我们可以使用elementsas E[],放入EE退出它,没有问题。

A problem only occurs when the (incorrect) fact that elementsis type E[]is "exposed" to the outside of the class, outside of the scope of the erasure of E, into a scope where someone has a concrete type argument for E. This usually happens when someone inadvertently makes elementspublic, or implements a method that returns it to the outside like

只有当(不正确的)的事实时发生的问题elements的类型是E[]“暴露”的类,的擦除的范围之外的外侧E,到了某人具有用于混凝土类型参数一个范围E。这通常发生在某人无意中elements公开或实现将其返回给外部的方法时,例如

E[] getElements() {
    return elements;
}

Then on the outside of the class, someone has a Stack<SomeSpecificType>, and call this method, and expect a SomeSpecificType[], which is not what it gets.

然后在类的外面,有人有一个Stack<SomeSpecificType>, 并调用这个方法,并期望得到一个SomeSpecificType[],这不是它得到的。

However, your Stackclass does not have such a method. So how are you "exposing" elements? The answer is that elementsis protected, and is therefore "exposed" to subclasses. In this case, the subclass, MinMaxStack, extends Stackwith a specific type for E, therefore, it "sees" elementsas a specific type of array, which it is not.

但是,您的Stack类没有这样的方法。那么你是如何“暴露”的elements呢?答案是:elementsprotected的,因此被“暴露”在子类中。在这种情况下,子类以特定类型 forMinMaxStack扩展,因此,它“将”视为特定类型的数组,而事实并非如此。StackEelements

回答by Radiodef

Here is the most-minimal code necessary to reproduce your exception.

这是重现异常所需的最少代码。

class Stack<E> {
    protected E[] elements = (E[])new Object[1];
}

class IntStack extends Stack<Integer> {
    void push(Integer i) {
        // subtly accessing elements as Integer[] which it's not
        elements[0] = i;
    }
}

Java generics are implemented with type erasureso after compilation, this code translates to something like this:

Java 泛型是通过类型擦除实现的,因此在编译后,此代码转换为如下所示:

class Stack {
    protected Object[] elements = new Object[1];
}

class IntStack extends Stack {
    void push(Integer i) {
        // throws ClassCastException
        ((Integer[])elements)[0] = i;
    }
}

Clearly a new Object[]is not an Integer[]. Notice how the cast gets moved to somewhere you did not explicitly put it. This is why (E[])new Object[size]was an unchecked castand displayed a warning.

显然 anew Object[]不是Integer[]。请注意演员如何移动到您没有明确放置的地方。这就是为什么(E[])new Object[size]是一个未经检查的铸造和显示警告信息。

Instead, you should use Object[]and perform the unchecked cast only when you need to return an element to the outside world.

相反,您应该Object[]仅在需要将元素返回给外部世界时才使用和执行未经检查的强制转换。

class Stack<E> {
    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;
    }
}

回答by Elliott Frisch

I believe the usual way is to pass the Classinto the constructor, and use Array.newInstance(Class<?>, int...)like

我相信通常的方法是将 传递Class给构造函数,并使用Array.newInstance(Class<?>, int...)类似

public Stack(Class<E> cls, int size){
    if(size <0){
        throw new IllegalArgumentException("Initial capacity cannot be "
            + "negative or zero");
    }
    elements = (E[]) Array.newInstance(cls, size);
}

Edit

编辑

From your update, pleasedon't use raw-types. With Java 7 and above you can use the diamond operator <>like

从您的更新中,不要使用raw-types。使用 Java 7 及更高版本,您可以使用菱形运算符,<>例如

Stack<Integer> st = new Stack<>(); 
st.push(ran.nextInt(100));

With earlier versions you specify the generic type like

对于早期版本,您可以指定泛型类型,例如

Stack<Integer> st = new Stack<Integer>(); 
st.push(ran.nextInt(100));

回答by Everv0id

It's clear now. You're trying to create your Stackwithout generic type. Consider Stack<Integer> st = new Stack<>();instead.

现在很清楚了。您正在尝试创建Stack没有泛型的类型。考虑一下Stack<Integer> st = new Stack<>();

回答by craftsmannadeem

Here is how you would fix it, you should not ever do (T[]) new Object[DEFAULT_CAPACITY];instead an abstraction should be there for example (T[]) new Comparable[DEFAULT_CAPACITY];

这是您将如何修复它,例如,您不应该这样做,(T[]) new Object[DEFAULT_CAPACITY];而应该在那里进行抽象(T[]) new Comparable[DEFAULT_CAPACITY];

public class ArrayStack<T extends Comparable<? super T>> implements Stack<T> {

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;
}
}