2009-01-13 12 views
11

¿Cómo es que, en Java, puedo escribirGenéricos de Java: Lista <Container<?>> = new LinkedList <Container <Double>>() está prohibido?

List<?> list = new LinkedList<Double>(); 

pero no

List<Container<?>> list = new LinkedList<Container<Double>>(); 

donde Container es sólo algo así como

public class Container<T> { ... } 

Esto ocurrió porque tengo un método que acepta a List<Container<?>>, y me gustaría usar Arrays.asList para pasarle argumentos:

process(Arrays.asList(new Container<Double>(), new Container<Double>())); 

Pero el lenguaje no permite esto, porque infiere el tipo de Arrays.asList ser List<Container<Double>>, y que no es asignable a List<Container<?>>.

Si añado un contenedor de cadena parametrizada a la llamada,

process(Arrays.asList(new Container<Double>(), new Container<String>())); 

todavía no funciona, ya que infiere el tipo de List<Container<? extends Serializable & Comparable<?>>> Arrays.asList. Solo si paso algo que no es Comparable ni Serializable, funciona correctamente.

Por supuesto, puedo poner un yeso y hacer que el compilador se calle, pero me pregunto si estoy haciendo algo mal aquí.

Respuesta

13

Cada parametrización debe comodín:

List<? extends Container<?>> list = new LinkedList<Container<Double>>(); 

Editar: Yo estaba buscando a través Angelika Langer's FAQ una explicación, pero no encontró uno (es probable que sea allí, pero escondido en algún lugar en las 500 páginas).

La forma de pensar sobre esto es que cada parametrización es independiente, y el compilador no deducirá información sobre la parametrización a menos que explícitamente lo indique.

2

Editar: Estaba buscando a través de las preguntas frecuentes de Angelika Langer para obtener una explicación, pero no encontré ninguna (probablemente esté allí, pero se esconde en alguna parte de las 500 páginas).

Muchas gracias por la respuesta. Encontré una explicación en las Preguntas frecuentes, y después de algunos entrecerrar los ojos, creo que lo entiendo.

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#What%20do%20multilevel%20wildcards%20mean?

2

Considera lo que pasaría si pudieras.

List<Container<Double>> list1 = new LinkedList<Container<Double>>(); 
List<Container<?>> list2 = list1; // this shouldn't be allowed, because of the below 
Container<String> foo = new Container<String>(); 
foo.add("hi"); 
list2.add(foo); // legal, because Container<String> is a subtype of Container<?> 
Container<Double> bar = list1.get(0); 
Double x = bar.get(0); // type error; it is actually a String object 
         // this indicates that type safety was violated 

Sin embargo, el uso de List<? extends Container<?>> no tiene este problema porque no se puede poner cualquier cosa (excepto null) en una lista de este tipo (porque no hay ningún tipo que se garantiza que sea un subtipo de "? extends Container<?>") .

Cuestiones relacionadas