The underlying issue is type erasure. The relevant implications of this means that an instance of the Stack
class doesn’t know it’s type arguments at run-time. This is the reason why you can’t just use the most natural solution here, array = new T[maxSize]
.
You’ve tried to work around this by creating an array using Array.newInstance(...)
, but unfortunately this array does not have elements of type T
either. In the code shown the elements are of type StackArray
, which is probably not what you intended.
One common way of dealing with this is to use an array of Object
internally to Stack
, and cast any return values to type T
in accessor methods.
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];
}
}
Note also you have a bug in the resizeArray()
method where maxSize
is never assigned a new value. You don’t really need to keep track of maxSize
, as you could just use array.length
.
I think there is also an issue with peek()
when the stack is empty in the original code.