2009-05-27 26 views
36

Tengo una pregunta de Java sobre genéricos. Declaré una lista genérica:Lista <? extiende MyType>

List<? extends MyType> listOfMyType; 

Luego, en algún método que intento crear instancias y añadir elementos a la lista:

listOfMyType = new ArrayList<MyType>(); 
listOfMyType.add(myTypeInstance); 

Dónde myTypeInstance es sólo un objeto de tipo MyType; no compilará Dice:

El método add (? Captura # 3 de extiende MyType) en el tipo de lista de captura < # 3 de ? extiende MyType> no es aplicable para los argumentos (MyType)

¿Alguna idea?

Respuesta

29

No se puede hacer un "put" con extends. Mira Generics - Get and Put rule.

+9

Como dice Josh Bloch: "Recuerde PECS: Productor Extiende, Súper del consumidor." Dado que listOfMyType es un consumidor (usted lo está agregando), 'super' es válido y' extends' no lo es. –

+0

Los enlaces ahora están rotos. –

+0

Punto de pedantería: puede 'poner' nulo' "con extiende".También puedes capturar el tipo y "poner" las referencias que has "obtenido" previamente. –

4

No debería ser necesario utilizar la sintaxis de captura de comodín en su caso, basta con declarar

List<MyType> listOfMytype; 

debería ser suficiente. Si quieres saber exactamente por qué, el Java Generics Tutorial tiene más de lo que siempre quisieras saber sobre la locura esotérica de los genéricos de Java. La página 20 aborda su caso específico.

En cuanto a por qué agregar con la captura de comodín no funciona, es porque el compilador no puede determinar exactamente qué subclase de MyType la lista será en todos los casos, por lo que el compilador emite un error.

22

considerar:

class MySubType extends MyType { 
} 

List<MySubType> subtypeList = new ArrayList<MySubType>(); 
List<? extends MyType> list = subtypeList; 
list.add(new MyType()); 
MySubType sub = subtypeList.get(0); 

sub contiene ahora una MyType que es muy mal.

+0

No debería el "list.get (0);" en realidad ser "subtipoLista.get (0);" ? – Zds

+0

@Zds Yup, corregido. Gracias. –

2

Hay un hilo similar aquí: How can elements be added to a wildcard generic collection?

para tener una idea de cómo funciona genéricos echa un vistazo a este ejemplo:

List<SubFoo> sfoo = new ArrayList<SubFoo>(); 
    List<Foo> foo; 
    List<? extends Foo> tmp; 

    tmp = sfoo; 
    foo = (List<Foo>) tmp; 

La cosa es, que no fue diseñado para locales/miembro variables, pero para las firmas de funciones, es por eso que es tan asqueroso.

2

No sé si esto realmente va a ayudar, pero esto es algo que tenía que utilizar al llamar a un método genérico de Spring Framework y con ganas de volver también una lista genérica:

public <T> List<T> findAll(String tableName,Class<?> table) { 
    String sql = "SELECT * FROM "+ tableName ; 
    List<?> entities = getSimpleJdbcTemplate().query(sql, 
      ParameterizedBeanPropertyRowMapper.newInstance(table)); 
      return (List<T>) entities; 
} 

Parece las necesidades de parametrización usted para usar el? inicie sesión en la lista para recibir los resultados y luego envíe la lista al tipo de devolución esperada.

Iam todavía deslumbrado por los genéricos ...

Cuestiones relacionadas