Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics problem and arrays

Tags:

java

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] = object;
}

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.

like image 435
Steve Avatar asked Jun 06 '11 18:06

Steve


People also ask

Can you use generics with an array?

Java allows generic classes, methods, etc. that can be declared independent of types. However, Java does not allow the array to be generic. The reason for this is that in Java, arrays contain information related to their components and this information is used to allocate memory at runtime.

Are there any issues when combining generics and arrays?

You will find that a simple statement like this will not even compile because the Java compiler does not allow this. To understand the reason, you first need to know two arrays are covariant and generics are invariant. Because of this fundamental reason, arrays and generics do not fit well with each other.

What is a generic array?

An array can be defined as a collection of items stored at contiguous memory locations. A generic array is independent of any data type and whose type of information is evaluated at runtime.

What is the disadvantages of using generics?

According to oracle documentation, the following points are the disadvantage of generics: Cannot instantiate Generic types with primitive types. Cannot create instances of type parameters. Cannot declare static fields whose types are type parameters.


1 Answers

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[].

like image 112
Mike Samuel Avatar answered Oct 11 '22 13:10

Mike Samuel