Skip to content
Advertisement

Parameter to pass in for type Class

I am trying to make a generic Stack class as shown

public class Stack<T> {
    public Stack(Class<T[]> type, int capacity) {
        this.capacity = capacity;
        array = type.cast(Array.newInstance(type,capacity));
    }
}

but am unsure of what to put in for type when instantiating since I thought of doing

MyClass[] c = new MyClass[0];
myStack = new Stack<MyClass>(c.getClass(), 100);

however I get the following error of

Required type: Class <MyClass[]>
Provided: Class <capture of ? extends MyClass[]>

so I thought of using

c.getClass().cast()

but I am unsure of what to put inside of cast() since it won’t take

Class<MyClass[]>

now I am stuck.

Advertisement

Answer

The overall design of this implementation is brittle. We are mixing two language constructs: arrays and generics. These two constructs differ in two major ways: arrays are covariant and retained, while generics are invariant and erased (see this question by eagertoLearn as to why). Mixing both is a recipe for disaster.
Furthermore, we need the component type to call Array::newInstance. Right now, we pass along the container-type.

I would recommend to use an Object[] as backing data structure and make the accessors generic to guarantee type-safety. This is also the approach taken by ArrayList. This approach will result in (at least) one unchecked cast that cannot be avoided. I leave it to the reader to

  • find the unchecked cast in ArrayList
  • argue why the cast is rectified and will never result in an actual ClassCastException as long as the interal array is never leaked.
Advertisement