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.
CodePudding user response:
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.
CodePudding user response:
You can refer to a typed array by adding []
after the class name:
myStack = new Stack<MyClass>(MyClass[].class, 100);