2011-06-06 14 views
6

Lo siento, no pude pensar en un título más conciso.Problema con los generadores y arreglos

Mi pregunta es ¿por qué el siguiente fragmento de código de trabajo:

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(); 
     } 
    } 
} 

cuando no va a funcionar haciendo que la matriz de objeto genérico como tan:

public abstract class TObjectPool<T> { 
protected T[] availableObjects; 

TObjectPool(int size){ 
    availableObjects = (T[]) new Object[size]; 
} 

Cuando los availableObjects [i] = nuevo RenderElement(); línea se ejecuta en este último ejemplo, obtengo una ClassCastException. Entiendo por qué funciona en el primer ejemplo, pero no por qué no funciona en el segundo. availableObjects debe ser una matriz de RenderElement y estoy tratando de darle un RenderElement. ¿Qué parte crucial de la información me falta?

Gracias por la ayuda.

actualización ...

Muchas gracias por las respuestas. Yo pensaba que entendía pero he logrado confundir a mí mismo de nuevo:

Si añado la función:

public void add(int index, T object){ 
    availableObjects[index] = object; 
} 

a la clase TObjectPool. Funcionará felizmente con la matriz T [].

Así que el nuevo TObjectPool y piscina con subclases son las siguientes:

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   
    } 
} 
} 

sé cómo puedo conseguir alrededor de esto ahora después de leer sus respuestas pero tengo curiosidad. ¿Alguien puede arrojar algo de luz sobre esta peculiaridad?

Gracias de nuevo.

+0

es una buena pregunta. ¡Lo estoy pensando durante los últimos 5 minutos y no sé la respuesta! – AlexR

+0

por favor! Danos [SSCCE] (http://sscce.org) fragmento de código de estilo. – MockerTim

Respuesta

4

El molde falla porque Object[] es una superclase de T[] para todas las T, pero no es un subtipo para ninguna T distinta de Object.

Si tiene un Class<T> disponible en tiempo de ejecución, puede usar Array.newInstance para crear un T[].

1

Usted podría tratar de usar la matriz es de tipo T.

He aquí cómo usted puede manejar eso: How to create a generic array in Java?

Utilizando la tipificación fuerte o débil. Estás tratando de usar la tipificación débil.

+1

Lo siento, amigo, pero eso no funciona en absoluto. No pasa la compilación. – AlexR

+0

Tienes razón. Puede usar esto: [link] (http://stackoverflow.com/questions/529085/java-how-to-generic-array-creation) – rambo

+0

Creo que eso no funciona, ya que las matrices en Java no son genéricas. – gpeche

1

Las matrices en Java no son genéricas, por lo que no puede aplicar los genéricos de Java a las matrices. En particular, lanzar desde Object[] a T[] como lo está haciendo en el constructor es incorrecto, y es muy probable que sea la causa de su error.

Sabiendo esto, puede utilizar el mismo truco que utiliza cuando se necesita crear una instancia de algo que no es genérico dentro de una clase genérica: pasar el objeto clase específica

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(); 
     } 
    } 
} 
Cuestiones relacionadas