【问题标题】:Generic stack implementation通用堆栈实现
【发布时间】:2017-07-27 01:35:45
【问题描述】:

我正在尝试实现一个通用堆栈。

界面如下

package stack;

public interface Stack<T>{
    void push(T number);
    T pop();
    T peek();
    boolean isEmpty();
    boolean isFull();
}

这是课程

package stack;

import java.lang.reflect.Array;
import java.util.EmptyStackException;

public class StackArray <T> implements Stack<T>{
    private int maxSize;
    private T[] array;
    private int top;

    public StackArray(int maxSize) {
        this.maxSize = maxSize;
//        @SuppressWarnings("unchecked")
        this.array = (T[]) Array.newInstance(StackArray.class, maxSize);
        this.top = -1;
    }

    private T[] resizeArray() {
        /**
         * create a new array double the size of the old, copy the old elements then return the new array */
        int newSize = maxSize * 2;
        T[] newArray = (T[]) Array.newInstance(StackArray.class, newSize);
        for(int i = 0; i < maxSize; i++) {
            newArray[i] = this.array[i];
        }
        return newArray;
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public boolean isFull() {
        return top == maxSize-1;
    }

    public void push(T element) {
        if(!this.isFull()) {
            ++top;
            array[top] = element;
        }
        else {
            this.array = resizeArray();
            array[++top] = element;
        }
    }

    public T pop() {
        if(!this.isEmpty())
            return array[top--];
        else {
            throw new EmptyStackException();
        }
    }

    public T peek() {
        return array[top];
    }
}

这是主类

package stack;


public class Main {
    public static void main(String[] args) {
        String word = "Hello World!";
        Stack <Character>stack = new StackArray<>(word.length());

//        for(Character ch : word.toCharArray()) {
//            stack.push(ch);
//        }

        for(int i = 0; i < word.length(); i++) {
            stack.push(word.toCharArray()[i]);
        }

        String reversedWord = "";
        while(!stack.isEmpty()) {
            char ch = (char) stack.pop();
            reversedWord += ch;
        }
        System.out.println(reversedWord);

    }
}

错误是

Exception in thread "main" java.lang.ArrayStoreException: java.lang.Character
    at stack.StackArray.push(StackArray.java:40)
    at stack.Main.main(Main.java:14)

第 40 行在 push 方法中

        array[top] = element;

附带问题: 有什么方法可以抑制构造函数中的警告? :)

【问题讨论】:

  • 你不想写 T[] array = new T[maxsize];而不是 (T[]) Array.newInstance(StackArray.class, maxSize); ?
  • Array.newInstance(StackArray.class, maxSize); 将为StackArray 元素创建一个数组。您正在尝试将 Character 放入该数组中,但这是不可能的。
  • 使用newInstance 是根本问题。只需声明一个 Object[] 并使用不安全的 T[] 强制转换和 @SuppressWarnings 注释,确保添加强制关联的代码注释来解释为什么它是安全的。

标签: java generics stack


【解决方案1】:

根本问题是类型擦除。这意味着Stack 类的实例在运行时不知道它的类型参数。这就是为什么你不能在这里只使用最自然的解决方案array = new T[maxSize]

您已尝试通过使用Array.newInstance(...) 创建一个数组来解决此问题,但不幸的是,该数组也没有T 类型的元素。在显示的代码中,元素的类型为 StackArray,这可能不是您想要的。

一种常见的处理方法是在内部使用Object 数组到Stack,并在访问器方法中将任何返回值转换为T 类型。

class StackArray<T> implements Stack<T> {
    private int maxSize;
    private Object[] array;
    private int top;

    public StackArray(int maxSize) {
        this.maxSize = maxSize;
        this.array = new Object[maxSize];
        this.top = -1;
    }

    // ... lines removed ...

    public T pop() {
        if(this.isEmpty())
            throw new EmptyStackException();
        return element(top--);
    }

    public T peek() {
        if(this.isEmpty())
            throw new EmptyStackException();
        return element(top);
    }

    // Safe because push(T) is type checked.
    @SuppressWarnings("unchecked")
    private T element(int index) {
        return (T)array[index];
    }
}

还请注意,resizeArray() 方法中存在一个错误,其中 maxSize 从未分配过新值。您实际上不需要跟踪maxSize,因为您可以使用array.length

我认为当原始代码中的堆栈为空时,peek() 也存在问题。

【讨论】:

  • 非常感谢您提供的额外错误。至于最初的问题,我从不习惯使用 Object,所以我将数组保留为 T 数组,但在构造函数中(在转换后)为它分配了一个 Object 数组,就像@Lew Bloch 建议的那样。也许这是同一件事:)
【解决方案2】:

您的代码创建了 StackArray 数组,然后您尝试在其中粘贴 Character 对象,就像您正在这样做一样:

static void add(Object arr[], Object o) {
    arr[0] = o;
}

public static void main(String[] args) {
    StackArray stack[] = new StackArray[1];
    Character c = 'x';
    add(stack, c);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-11
    • 2013-01-25
    • 2023-04-10
    • 1970-01-01
    • 2017-09-03
    • 2010-11-27
    • 2013-12-11
    • 1970-01-01
    相关资源
    最近更新 更多