0

In the code segment below, I want to create the array object inside the GenericStack class constructor. I understand why this is a problem. As per my understanding, "T" can be any class as far as the compiler is concerned. This class T can be an abstract class and hence cannot be instantiated. For example, java.lang.Number class is an abstract class and I could very well pass java.lang.Number for T.

My question now is the following:

Is there a way to tell the compiler (by some bounded parameters or perhaps something else) that the class that I am going to pass in place of T will be a concrete class that can be instantiated ? I know that I could easily create the array inside the main and then pass a reference but I find that to be a bit cluttered approach to implementing such requirement.

public class GenericStack<T> {
    
    //Data for the stack is an array but can be changed to list.
    public static final int stackSize = 10;
    private T[] stackData;
    private int tos;

    public GenericStack(int size) {
        stackData = new T[size];  // This line will error out
        tos = -1;
    }

    public T pop() {
        try {
            return stackData[tos--];
        } catch (Exception e) {
            System.out.println("Stack empty.Cannot POP from an empty stack.");
            return null;
        }
    }

    public void push(T stackObj) {
        try {
            stackData[++tos] = stackObj;
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Stack is full. Cannot push a element into a full stack.");
        }
    }

    public static void main(String[] args) {
        GenericStack<Integer> intStack = new GenericStack<Integer>(GenericStack.stackSize);
        GenericStack<String> stringStack = new GenericStack<String>(GenericStack.stackSize);
    }
}
  • The only option that could keep your single `size` argument, that I can think of, involves reflection and `Array#newInstance`. Or, you just create an `Object[]` instead of `T[]` and cast each element as it's added or removed. – PPartisan Oct 30 '20 at 20:11
  • 1
    See also https://stackoverflow.com/questions/529085/how-to-create-a-generic-array-in-java#530289 – andy Oct 30 '20 at 20:15
  • I will have to read up on reflection as I don't know much about that. The second approach is exactly what I am trying to avoid. With Object[] , you are basically sacrificing type-safety and you have to employ type casts. My whole point of using generics in the first place is to get type safety and to avoid explicit casts. – Sushrut Kaul Oct 30 '20 at 20:15
  • 1
    Even the API classes such as `ArrayList` back their list with an array of `Object` and then cast to the actual type upon retrieval. A stack only has so many retrieval options so casting should not be that burdensome. – WJS Oct 30 '20 at 20:24
  • You _cannot_ avoid the explicit casts for a low-level data structure like this. – Louis Wasserman Oct 30 '20 at 20:57

1 Answers1

0

You have to do something like this.

public GenericStack(int size) {
      stackData = new Object[size]; 
      tos = -1;
 }

Then later

@SuppressWarning("unchecked")
public T pop() {
 // check stack state
 return (T)stackData[++tos];
}
WJS
  • 22,083
  • 3
  • 14
  • 32