Reputation: 16192
I have a container class that looks like this. (I'm removing all logic methods to reduce clutter)
public abstract class Container<T> {
protected T[] array;
public Container(int capacity) {
array = (T[]) new Object[capacity];
}
public T[] array() {
return array;
}
}
This class is used, like so:
public final class ItemContainer extends Container<Item> {
public ItemContainer(int capacity) {
super(capacity);
}
}
This container now, should hold an array of Items. However when trying to pass it to an Item[]
to be used, the following error is presented:
Exception in thread "ForkJoinPool-2-worker-1" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Lcom.oblivion.entity.item.Item;
How can I get around this?
Upvotes: 1
Views: 56
Reputation: 109557
public Container(Class<T> clazz, int capacity) {
array = (T[]) Array.newInstance(clazz, capacity);
}
The need for a cast is a bit of a mishap in language design. There is an overloaded newInstance
with multiple dimensions, hence in the case of T[]...[]
a generic result type cannot be done.
You might want to store the component class for object creation or casts:
T t = clazz.cast(object);
T t = clazz.newInstance();
Upvotes: 1
Reputation: 111259
When you create an array of Object (or any other object in fact), it doesn't change types when you cast, in fact casting to the generic T[] has no effect at all. Therefore the array
method returns an array of Object, which the caller tries to cast implicitly to an array of Item, and that of course fails.
If you want to create an array of the parametric type you should have a method that accepts a Class<T>
. Then you can create the array using the Array.newInstance method.
Alternatively you can use the approach used by ArrayList: use an array of Object internally and require the caller to pass in an array of the appropriate type if they want a snapshot of the data.
Upvotes: 1