2012-02-20 15 views
11

Si tengo una clase abstracta como esto:llamar al constructor de un tipo genérico

public abstract class Item 
{ 
    private Integer value; 
    public Item() 
    { 
     value=new Integer(0); 
    } 
    public Item(Integer value) 
    { 
     this.value=new Integer(); 
    } 
} 

Y algunas clases de artículos que se derivan de la siguiente manera:

public class Pencil extends Item 
{ 
    public Pencil() 
    { 
     super(); 
    } 
    public Pencil(Integer value) 
    { 
     super(value); 
    } 
} 

no he entendido por qué no puedo llamar al constructor utilizando un genérico:

public class Box <T extends Item> 
{ 
    T item; 
    public Box() 
    { 
     item=new T(); // here I get the error 
    } 
} 

sé que es posible tener un tipo que no tiene un constructor, pero esta ca es imposible porque Pencil tiene el constructor sin parámetros, y Item es abstracto. Pero obtengo este error de eclipse: no puedo instanciar el tipo T
No entiendo por qué, y cómo evitar esto?

+0

Considere el caso cuando se tiene otra clase que extiende 'Item', excepto esta clase tiene solo un constructor que insiste en al menos un argumento. –

+0

posible duplicado de [¿Cómo puedo instanciar un tipo genérico en Java?] (Http://stackoverflow.com/questions/6916346/how-can-i-instantiate-a-generic-type-in-java) –

+0

posible duplicar de [Crear instancia de tipo genérico en Java?] (http://stackoverflow.com/questions/75175/create-instance-of-generic-type-in-java) –

Respuesta

9

No hay manera de utilizar el sistema de tipos de Java para hacer cumplir una jerarquía de clases que tiene una firma uniforme para los constructores de sus subclases.

considerar:

public class ColorPencil extends Pencil 
{ 
    private Color color; 

    public ColorPencil(Color color) 
    { 
     super(); 
     this.color=color; 
    } 
} 

Esto hace colorpencil T válida (que se extiende de artículos). Sin embargo, no hay ningún constructor no-arg para este tipo. Por lo tanto, T() no tiene sentido.

Para hacer lo que quiera, debe usar la reflexión. No puede beneficiarse de la comprobación de errores en tiempo de compilación.

11

Esto se debe a que Java utiliza el borrado de implementar los genéricos, ver esto:

citar las partes pertinentes de la anterior artículo de Wikipedia:

Los genéricos son inspeccionados en tiempo de compilación para la corrección de tipo. La información de tipo genérico se elimina en un proceso llamado borrado de tipo.

Como resultado del borrado de tipo, los parámetros de tipo no se pueden determinar en tiempo de ejecución.

En consecuencia, la creación de instancias de una clase Java de un tipo parametrizado es imposible porque la instanciación requiere una llamada a un constructor, que no está disponible si el tipo es desconocido.

Puede solucionar esto proporcionándole la clase usted mismo. Esto está muy bien explicado aquí:

+0

Muchas gracias. Esta respuesta fue exactamente lo que estaba buscando o dejé decir: coincide perfectamente con mi incomprensión de la implementación genérica de Java. :-) –

+0

@MichaelDorner ¡Claro, me alegro de ayudar! –

0

Debido a que en tiempo de ejecución se desconoce el tipo de camiseta.

1

T es un alias para el tipo real de su clase va a manejar, por ejemplo, si usted instancia Box<Item> continuación T es en realidad un alias para Item. Cuando declare T extends Item, sabrá que T tendrá al menos la misma interfaz que Item, por lo que puede tratarlo como tal.

Creo que lo que realmente quiere hacer no es crear una instancia del campo item en Box, sino implementar un par de métodos para permitirle manipular ese campo.

public class Box<T extends Item> { 
    private T item; 

    public T getItem() { 
     return this.item; 
    } 

    public void setItem(T item) { 
     return this.item = item; 
    } 
} 
0

Es imposible utilizar T para llamar a un constructor porque si sería posible que después de una compilación que se obtiene el código de la siguiente manera:

public class Box{ 
    Object item; 
    public Box(){ 
     item = new Object(); 
    } 
} 

Así que si desea utilizar este código y pasar algún objeto de esperas que se llame al constructor de algún tipo específico, pero en su lugar obtienes el constructor Object.

+0

Bueno, solo imposible debido a los detalles de cómo se implementan los genéricos de Java – Alexander

0

Puede colocar un método abstracto para que la clase implementadora pueda determinar cómo construir el nuevo objeto.

public abstract T constructT(); 

y en lugar de llamar

T t = new T() 

que llamarían

T t = constructT(); 

En su implementación llamarla sería creada como:

new Box<Integer>() { 
    public Integer constructT(){ return new Integer(); } 
} 
Cuestiones relacionadas