¿Cómo es que en Java no podemos hacer?
List<List> aList = new ArrayList<List>();
Aunque esto está bien:
List aList = new ArrayList();
El mensaje de error del comstackdor es:
Type mismatch: cannot convert from ArrayList<List> to List<List>
En Java, si el Car
es una clase derivada de Vehicle
, entonces podemos tratar a todos los Cars
como Vehicles
; un Car
es un Vehicle
. Sin embargo, una List
de Cars
no es también una List
de Vehicles
. Decimos que List
no es covariante con List
.
Java requiere que indique explícitamente cuándo desea utilizar la covarianza y la contravariancia con comodines, representados por ?
simbólico. Mire donde sucede su problema:
List> l = new ArrayList>(); // ---------------- ------ // // "? extends Number" matched by "Number". Success!
La List extends Number>
interna List extends Number>
List extends Number>
funciona porque Number
realmente extiende Number
, por lo que coincide con ” ? extends Number
“. Hasta aquí todo bien. ¿Que sigue?
List> l = new ArrayList>(); // ---------------------- ------------ // // "List extends Number>" not matched by "List". These are // different types and covariance is not specified with a wildcard. // Failure.
Sin embargo, el parámetro de tipo interno combinado List extends Number>
List extends Number>
no coincide con List
; los tipos deben ser exactamente idénticos . Otro comodín le dirá a Java que este tipo combinado también debe ser covariante:
List extends List extends Number>> l = new ArrayList>();
No estoy muy familiarizado con la syntax de Java, pero parece que su problema es este:
Covarianza y contradicción
Definitivamente deberías usar el? escriba wildcard cuando sea apropiado, no lo evite como regla general. Por ejemplo:
public void doThingWithList(List> list);
le permite pasar una List
o una List
.
public void doThingWithList(List> list);
le permite solo pasar argumentos declarados como List
. Una pequeña distinción, sí, pero usar el comodín es poderoso y seguro . Contrariamente a cómo puede parecer, una List
no es una subclase, o no es asignable, de la List
. Tampoco es List
una subclase de List extends Number
List extends Number
, razón por la cual el código anterior no se comstack.
Su extracto no se comstack porque List extends Number>
List extends Number>
no es del mismo tipo que List
. El primero es un supertipo de este último.
¿Has probado esto? Aquí estoy expresando que la Lista es covariante en su argumento de tipo, por lo que aceptará cualquier subtipo de List extends Number>
List extends Number>
(que incluye List
).
List extends List extends Number>> aList = new ArrayList>();
O incluso esto. Aquí el parámetro tipo para ArrayList en el lado derecho es el mismo que el parámetro tipo en el lado izquierdo, por lo que la varianza no es un problema.
List> aList = new ArrayList>();
Deberías poder decir
List> aList = new ArrayList>();
Tiendo a evitar el ?
escriba comodín siempre que sea posible. Considero que el gasto incurrido en la anotación tipo no vale la pena el beneficio.
List> aList = new ArrayList>(); aList.add(new ArrayList());