2012-02-28 16 views

Respuesta

11

Sí.

List<Base> puede contener una mezcla de diferentes cosas que todos derivan de Base. List<? extend Base> contiene elementos homogéneos (en el sentido de que todos deben derivar de algún tipo específico desconocido que a su vez deriva de Base).

Dicho de otra manera, List<? extends Base> es la clase base para List<T extends Base>. Entonces puede pasar un List<T extends Base> a cualquier método que tome un List<? extends Base>. Lo mismo no es cierto para los métodos que toman un List<Base>.

+6

En particular, no puede agregar un objeto de tipo 'Base' a una' Lista '. –

+3

@LouisWasserman: No solo eso, pero no puede agregar * any * objeto (excepto 'null') a' List ', porque no sabes qué tipo representa el'? '. –

+0

@LouisWasserman: ¿En resumen, List se puede pasar a cualquier método que tome cualquiera de List , Lista , Lista , o Lista ? Entonces, ¿por qué alguien querría usar List ? Lo que también me desconcierta es que puedes hacer .add (...) en ambos List y Lista , donde '...' puede ser cualquier cosa que sea Base o derivada (directa o indirectamente) de Base. – user113454

5

List<Base> list puede contener elementos de tipo Base o cualquiera de sus subtipos. Algunos ejemplos de las clases de JDK:

List<Object> objects = new ArrayList<Object>(); 
objects.add(new Object()); // adding an Object instance 
objects.add("I am a String"); // a String instance is also an Object 
objects.add(Integer.valueOf(5)); // an Integer instance is also an Object 

Pero cuando se recuperan los elementos, puede asignar únicamente a las variables de la clase Object, porque Object es el parámetro de tipo de la lista declarado.

Object first = objects.get(1); 
Object second = objects.get(2); 
Object third = objects.get(3); 

Sus clases reales de ejecución son todavía Object, String y Integer, por lo que pueden echarlos a esos tipos y trabajar con ellos como tal, pero este tipo de moldes pueden fallar en tiempo de ejecución con un ClassCastException si no se hace bien y es En general, no es una buena idea trabajar con listas de esa manera.

List<? extends Base> list es una declaración de que no es en realidad designado para la declaración de variables, porque como ya se ha mencionado en el comentario de Daniel Pryden - Puede no add() cualquier objeto en ella, sólo null s.

List<? extends String> list = new ArrayList<? extends String>(); 
list.add("a String")); // compile error! 

Pero se puede utilizar una expresión tan acotada comodín para los parámetros de los métodos genéricos. Un ejemplo de la List sí es el método addAll() cuya firma es la siguiente:

boolean addAll(Collection<? extends E> c); 

Esto le permite hacer algo como esto:

List<String> strings = Arrays.asList("a", "b"); 
List<Object> objects = new ArrayList<Object>(); 
objects.addAll(strings); 

Sin la <? extend E> comodín que no sería posible añadir aquellos String s en List de Object s, porque los tipos genéricos (a diferencia de las matrices) no son covariantes. Eso significa que un List<String>no es un subtipo de List<Object>. Pero cualquier String es un Object, ¿verdad? Por lo tanto, es necesario declarar el parámetro del método con el comodín delimitado; un List<String>es, un subtipo de List<? extends Object>.

Una vez más, tengo que señalar que el comodín delimitado está designado principalmente para los parámetros de método genérico , no para los tipos de retorno de método o las declaraciones de variables.

Cuestiones relacionadas