Sorry I couldnt think of a more concise title.
My question is why does the following piece of code work:
public abstract class TObjectPool<T> {
protected Object[] availableObjects;
TObjectPool(int size){
availableObjects = new Object[size];
}
protected class RenderElementPool extends TObjectPool<RenderElement>{
@Override
public void fill() {
for (int i = 0; i < capacity; i++) {
availableObjects[i] = new RenderElement();
}
}
}
when it will not work making the Object array a generic as so:
public abstract class TObjectPool<T> {
protected T[] availableObjects;
TObjectPool(int size){
availableObjects = (T[]) new Object[size];
}
When the availableObjects[i] = new RenderElement(); line is executed in this latter example I get a ClassCastException. I understand why it works in the first example but not why it doesn't in the second. availableObjects should be an array of RenderElement and I am trying to give it a RenderElement. What crucial bit of info am I missing?
Thanks for the help.
Update...
Thanks very much for the responses. I thought I understood but I have managed to confuse myself again:
If I add the function:
public void add(int index, T object){
availableObjects[index] = obj开发者_高级运维ect;
}
to the TObjectPool class. It will happily work with the T[] array.
So the new TObjectPool and subclassed pool are as follows:
public abstract class TObjectPool<T> {
T[] availableObjects;
TObjectPool(int size){
availableObjects = (T[])new Object[size];
capacity = size;
count = capacity;
fill();
}
public void add(int index, T object){
availableObjects[index] = object;
}
protected class RenderElementPool extends TObjectPool<RenderElement>{
@Override
public void fill() {
for (int i = 0; i < capacity; i++) {
add(i, new RenderElement()); //this works
//availableObjects[i] = new RenderElement(); //this gives an exception
}
}
}
I know how I can get round this now after reading your responses but I am curious. Can anyone shed some light into this peculiarity?
Thanks again.
The cast fails because Object[]
is a super class of T[]
for all T, but not a subtype for any T other than Object
.
If you have a Class<T>
available at runtime, you can use Array.newInstance
to create a T[]
.
You could try to use the array being of type T.
Here's how you can manage that: How to create a generic array in Java?
Using either the strong or weak typing. You are trying to use the weak typing.
Arrays in Java are not generic, so you cannot apply Java generics to arrays. In particular, casting from Object[]
to T[]
as you are doing in the constructor is wrong, and it is most probably the cause of your error.
Knowing this, you can use the same trick you use when you need to instantiate something that is not generic inside a generic class: pass the specific class object
TObjectPool(int size, Class<T> klass) {
availableObjects = Array.newInstance(klass, size);
}
...
protected class RenderElementPool extends TObjectPool<RenderElement>{
// Pass the class object to super constructor
public RenderElementPool(int size) {
super(size, RenderElement.class);
}
...
@Override
public void fill() {
for (int i = 0; i < capacity; i++) {
availableObjects[i] = new RenderElement();
}
}
}
精彩评论