簡體   English   中英

Ljava.lang.Object; 無法轉換為[Ljava.lang.Integer

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

我編寫了一個泛型類,下面是該類的構造函數。 我想做這樣的事情就像寫在線一樣

elements = (E[])new Object[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");
    }
    ArrayList<Integer> ar = new ArrayList<Integer>();
    elements = (E[])new Object[size];
}
}

有什么方法可以解決這些問題嗎? E的聲明是

protected E[] elements = null;    

這就是我試圖打電話的方式

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

更新伙計們,感謝您的幫助。 我正在搞亂泛型,所以問題正在形成。 以下是創建問題的所有代碼 -

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

更新2 :看起來,除了傳遞下面的答案中提到的類類型,我們無法做到這一點。

基本上,當你做(E[])new Object[size] ,這是一個謊言。 對象的實際運行時類是Object[] ,它不是E[]的子類型,無論E是什么(除非EObject )。 因此,演員在理論上是不正確的。 但是,這不會立即產生任何問題,因為在Stack類中, E被擦除到其上限,在本例中為Object 所以在Stack類中,我們可以使用elements作為E[] ,並將E放入並從中獲取E ,沒有問題。

只有當elements類型為E[]的(不正確的)事實被“暴露”到類的外部(超出E的擦除范圍)進入某個范圍內,其中某個人具有E的具體類型參數時,才會出現問題。 。 這通常發生在有人無意中使elements公開,或實現一個將其返回到外部的方法時

E[] getElements() {
    return elements;
}

然后在類的外部,有人有一個Stack<SomeSpecificType> ,並調用此方法,並期望SomeSpecificType[] ,這不是它得到的。

但是,您的Stack類沒有這樣的方法。 那你怎么“暴露” elements 答案是elements protected ,因此“暴露”到子類。 在這種情況下,子類MinMaxStack使用E的特定類型擴展Stack ,因此,它將elements “視為”特定類型的數組,而不是。

這是重現異常所需的最小代碼。

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泛型是使用類型擦除實現的,因此在編譯之后,此代碼轉換為如下所示:

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

我相信通常的方法是將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);
}

編輯

從您的更新, 不要使用原始類型 使用Java 7及更高版本,您可以使用菱形運算符<>

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

對於早期版本,您可以指定泛型類型

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

現在很清楚了。 您正在嘗試創建沒有泛型類型的Stack 考慮Stack<Integer> st = new Stack<>(); 代替。

以下是修復它的方法,你不應該做(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;
}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM