type - Lista genérica de Java<Lista<? extiende el número>>
java generics parameter (5)
Definitivamente deberías usar el? escriba wildcard cuando sea apropiado, no lo evite como regla general. Por ejemplo:
public void doThingWithList(List<List<? extends Number>> list);
le permite pasar una List<Integer>
o una List<Long>
.
public void doThingWithList(List<List<Number>> list);
le permite solo pasar argumentos declarados como List<Number>
. Una pequeña distinción, sí, pero usar el comodín es poderoso y seguro . Contrariamente a cómo puede parecer, una List<Integer>
no es una subclase, o no es asignable, de la List<Number>
. Tampoco es List<Integer>
una subclase de List<? extends Number
List<? extends Number
, razón por la cual el código anterior no se compila.
¿Cómo es que en Java no podemos hacer?
List<List<? extends Number>> aList = new ArrayList<List<Number>>();
Aunque esto está bien:
List<? extends Number> aList = new ArrayList<Number>();
El mensaje de error del compilador es:
Type mismatch: cannot convert from ArrayList<List<Number>> to List<List<? extends Number>>
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<Car>
no es covariante con List<Vehicle>
.
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<List<? extends Number>> l = new ArrayList<List<Number>>();
// ---------------- ------
//
// "? 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<List<? extends Number>> l = new ArrayList<List<Number>>();
// ---------------------- ------------
//
// "List<? extends Number>" not matched by "List<Number>". 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<Number>
; 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<List<Number>>();
No estoy muy familiarizado con la sintaxis de Java, pero parece que su problema es este:
Su extracto no se compila porque List<? extends Number>
List<? extends Number>
no es del mismo tipo que List<Number>
. 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<Number>
).
List<? extends List<? extends Number>> aList = new ArrayList<List<Number>>();
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<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();
Deberías poder decir
List<List<Number>> aList = new ArrayList<List<Number>>();
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<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();
aList.add(new ArrayList<Integer>());