una ultimo ordenada nodo listas lista ligada insertar fuente estructura enlazadas enlazada eliminar datos con como codigo agenda java generics

java - ultimo - ¿Cómo puedo agregar a List<? se extiende Número> estructuras de datos?



lista enlazada ordenada java (4)

"List ''<''? Extends Number> es en realidad un comodín de límite superior!

El comodín de límite superior dice que cualquier clase que amplíe Number o Number se puede usar como el tipo de parámetro formal: el problema surge del hecho de que Java no sabe qué tipo es realmente List . Tiene que ser un tipo EXACTO y ÚNICO. Espero que ayude :)

Tengo una lista que se declara así:

List<? extends Number> foo3 = new ArrayList<Integer>();

Traté de agregar 3 a foo3. Sin embargo, recibo un mensaje de error como este:

The method add(capture#1-of ? extends Number) in the type List<capture#1-of ? extends Number> is not applicable for the arguments (ExtendsNumber)


No puedes (sin moldes inseguros). Solo puedes leer de ellos.

El problema es que no sabes de qué exactamente es una lista. Podría ser una lista de cualquier subclase de Número, de modo que cuando tratas de ponerle un elemento, no sabes que el elemento realmente cabe en la lista.

Por ejemplo, la Lista podría ser una lista de Byte , por lo que sería un error colocar un Float en ella.


Usted podría hacer esto en su lugar:

List<Number> foo3 = new ArrayList<Number>(); foo3.add(3);


Lo siento, pero no puedes.

La declaración de comodín de List<? extends Number> foo3 List<? extends Number> foo3 significa que la variable foo3 puede contener cualquier valor de una familia de tipos (en lugar de cualquier valor de un tipo específico). Significa que cualquiera de estas son asignaciones legales:

List<? extends Number> foo3 = new ArrayList<Number>; // Number "extends" Number List<? extends Number> foo3 = new ArrayList<Integer>; // Integer extends Number List<? extends Number> foo3 = new ArrayList<Double>; // Double extends Number

Entonces, dado esto, ¿qué tipo de objeto podría agregar a la List foo3 que sería legal después de cualquiera de las posibles asignaciones de ArrayList anteriores?

  • No puede agregar un Integer porque foo3 podría estar apuntando a una List<Double> .
  • No puede agregar un Double porque foo3 podría estar apuntando a una List<Integer> .
  • No puede agregar un Number porque foo3 podría estar apuntando a una List<Integer> .

No puede agregar ningún objeto a la List<? extends T> List<? extends T> porque no puede garantizar a qué tipo de List apunta realmente, por lo que no puede garantizar que el objeto esté permitido en esa List . La única "garantía" es que solo puede leer de ella y obtendrá una T o subclase de T

La lógica inversa se aplica a super , por ejemplo, List<? super T> List<? super T> . Estos son legales:

List<? super Number> foo3 = new ArrayList<Number>; // Number is a "super" of Number List<? super Number> foo3 = new ArrayList<Object>; // Object is a "super" of Number

No puede leer el tipo específico T (por ejemplo, Number ) de List<? super T> List<? super T> porque no se puede garantizar a qué tipo de List apunta realmente. La única "garantía" que tiene es que puede agregar un valor de tipo T (o cualquier subclase de T ) sin violar la integridad de la lista a la que se está apuntando.

El ejemplo perfecto de esto es la firma de Collections.copy() :

public static <T> void copy(List<? super T> dest,List<? extends T> src)

Observe cómo se usa la declaración de la lista src para permitirme pasar cualquier Lista de una familia de tipos de Lista relacionados y aún garantizar que producirá valores de tipo T o subclases de T. Pero no puede agregar a la lista src .

La declaración de la lista dest usa super para permitirme pasar cualquier lista de una familia de tipos de listas relacionados y aún así garantizar que pueda escribir un valor de un tipo específico T en esa lista. Pero no se puede garantizar que lea los valores del tipo específico T si leo de la lista.

Así que ahora, gracias a los comodines genéricos, puedo hacer cualquiera de estas llamadas con ese único método:

// copy(dest, src) Collections.copy(new ArrayList<Number>(), new ArrayList<Number()); Collections.copy(new ArrayList<Number>(), new ArrayList<Integer()); Collections.copy(new ArrayList<Object>(), new ArrayList<Number>()); Collections.copy(new ArrayList<Object>(), new ArrayList<Double());

Considere este código confuso y muy amplio para ejercitar su cerebro. Las líneas comentadas son ilegales y la razón por la cual está indicada en el extremo derecho de la línea (necesita desplazarse para ver algunas de ellas):

List<Number> listNumber_ListNumber = new ArrayList<Number>(); //List<Number> listNumber_ListInteger = new ArrayList<Integer>(); // error - can assign only exactly <Number> //List<Number> listNumber_ListDouble = new ArrayList<Double>(); // error - can assign only exactly <Number> List<? extends Number> listExtendsNumber_ListNumber = new ArrayList<Number>(); List<? extends Number> listExtendsNumber_ListInteger = new ArrayList<Integer>(); List<? extends Number> listExtendsNumber_ListDouble = new ArrayList<Double>(); List<? super Number> listSuperNumber_ListNumber = new ArrayList<Number>(); //List<? super Number> listSuperNumber_ListInteger = new ArrayList<Integer>(); // error - Integer is not superclass of Number //List<? super Number> listSuperNumber_ListDouble = new ArrayList<Double>(); // error - Double is not superclass of Number //List<Integer> listInteger_ListNumber = new ArrayList<Number>(); // error - can assign only exactly <Integer> List<Integer> listInteger_ListInteger = new ArrayList<Integer>(); //List<Integer> listInteger_ListDouble = new ArrayList<Double>(); // error - can assign only exactly <Integer> //List<? extends Integer> listExtendsInteger_ListNumber = new ArrayList<Number>(); // error - Number is not a subclass of Integer List<? extends Integer> listExtendsInteger_ListInteger = new ArrayList<Integer>(); //List<? extends Integer> listExtendsInteger_ListDouble = new ArrayList<Double>(); // error - Double is not a subclass of Integer List<? super Integer> listSuperInteger_ListNumber = new ArrayList<Number>(); List<? super Integer> listSuperInteger_ListInteger = new ArrayList<Integer>(); //List<? super Integer> listSuperInteger_ListDouble = new ArrayList<Double>(); // error - Double is not a superclass of Integer listNumber_ListNumber.add(3); // ok - allowed to add Integer to exactly List<Number> // These next 3 are compile errors for the same reason: // You don''t know what kind of List<T> is really // being referenced - it may not be able to hold an Integer. // You can''t add anything (not Object, Number, Integer, // nor Double) to List<? extends Number> //listExtendsNumber_ListNumber.add(3); // error - can''t add Integer to *possible* List<Double>, even though it is really List<Number> //listExtendsNumber_ListInteger.add(3); // error - can''t add Integer to *possible* List<Double>, even though it is really List<Integer> //listExtendsNumber_ListDouble.add(3); // error - can''t add Integer to *possible* List<Double>, especially since it is really List<Double> listSuperNumber_ListNumber.add(3); // ok - allowed to add Integer to List<Number> or List<Object> listInteger_ListInteger.add(3); // ok - allowed to add Integer to exactly List<Integer> (duh) // This fails for same reason above - you can''t // guarantee what kind of List the var is really // pointing to //listExtendsInteger_ListInteger.add(3); // error - can''t add Integer to *possible* List<X> that is only allowed to hold X''s listSuperInteger_ListNumber.add(3); // ok - allowed to add Integer to List<Integer>, List<Number>, or List<Object> listSuperInteger_ListInteger.add(3); // ok - allowed to add Integer to List<Integer>, List<Number>, or List<Object>