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.