0

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.

nix_s
  • 38
  • 5

2 Answers2

6

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.
Turing85
  • 18,217
  • 7
  • 33
  • 58
1

You can refer to a typed array by adding [] after the class name:

myStack = new Stack<MyClass>(MyClass[].class, 100);
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • 1
    OP uses `c.getClass()` (which should be equivalent to `MyClass[].class`). Can you explain why your solution works, while OP's solution does not? – Turing85 Jan 01 '22 at 19:36
  • [`Array.newInstance`](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Array.html#newInstance-java.lang.Class-int-) requires the *component type*, so this will most probably not work as expected. – Izruo Jan 01 '22 at 19:38
  • Thanks it does work, not sure why I didn't think of using .class instead of getClass() in the first place. I must have assumed they are practically the same when they are clearly not!! – nix_s Jan 01 '22 at 19:47
  • @Turing85: Because `c.getClass()` has type `Class extends MyClass[]>`, due to the fact that `c`'s actual runtime class might be a subclass of `MyClass[]`. On the other hand, `MyClass[].class` has type `Class`. – newacct Jan 09 '22 at 07:15