¿Por ListList <? Super E> es la lista <? Lista extiende <? Super E >> pero no List <List <? Super E >>

plátano:

Tengo una interfaz genérica interface ListList<E> extends List<List<E>>. Por alguna razón, no puedo echar ListList<? super T>a List<List<? super T>>. ¿Hay alguna forma de hacerlo y por qué no funciona?

Por el momento ya he intentado lo siguiente:

  1. Asignación sencilla, de esta manera me las he arreglado para asignar ListList<? super T>a List<? extends List<? super T>>(1), pero cuando intento para asignar ListList<? super T>a List<List<? super T>>me sale Incompatible typeserror en tiempo de compilación (1.1).
  2. Conversión de tipo explícita, que no funciona debido a la misma Incompatible typeserror de tiempo de compilación (2).
  3. La conversión a tipo de prima ListList, funciona (3), pero que no me gustan los tipos de primas.
  4. Añadiendo todos los elementos de ListList<? super T>a List<? extends List<? super T>>, funciona (4), pero necesito una solución más general que funciona no sólo con ListList<E>, pero con cualquier tipo genérico.

Aquí está mi código:

ListList<? super T> var = new ArrayListList<>();
List<? extends List<? super T>> work = var; // (1)
List<List<? super T>> notWork = var; // (1.1)
List<List<? super T>> explicit = (List<List<? super T>>) var; // (2)
List<List<? super T>> raw = (ListList) var; // (3)
List<List<? super T>> copy = new ArrayList<>(); // (4)
copy.addAll(var); // (4)

Yo he esperado ListList<? super T>ser List<List<? super T>>, pero parecía ser List<? extends List<? super T>>. Necesito saber qué es y cómo puedo echarlo a List<List<? super T>>sin primas y tipos de elementos a copiar.

rgettman:

En un primer momento, parece que estas asignaciones deben todos tener éxito, pero no lo hacen debido a la wildcard interior ? super T. Si eliminamos los comodines, entonces todas las tareas de compilación.

public static <T> void test() {
    ListList<T> var = new ArrayListList<>();
    List<? extends List<T>> work = var; // Compiles
    List<List<T>> notWork = var; // Compiles
    List<List<T>> explicit = (List<List<T>>) var; // Compiles
    List<List<T>> raw = (ListList) var; // Compiles with warning
    List<List<T>> copy = new ArrayList<>(); // Compiles
    copy.addAll(var); // Compiles
}

Todavía recibo el aviso de conversión sin control durante (3), pero todos ellos siguen compilación.

A primera vista parece que se declara la interfaz

ListList<E> extends List<List<E>>

hace un ListListequivalente a una Listde Lists. Sin embargo lo que ha hecho es tomar un parámetro de tipo anidado y lo hizo el parámetro de tipo principal. La razón de que eso hace la diferencia es comodines anidados no realizan la captura de comodín .

Un comodín anidada aquí significa "una lista de listas de cualquier tipo que coincide con el límite", pero un nivel principal Comodín aquí significa "una 'listlist' de un específico todavía tipo desconocido que coincida con el límite".

No se puede añadir un objeto que es un supertipo del límite inferior a una colección, porque el parámetro de tipo - un tipo específico aún desconocido - puede ser el límite real.

List<? super Integer> test2 = new ArrayList<>();
test2.add(2);   // Compiles; can add 2 if type parameter is Integer, Number, or Object
test2.add((Number) 2);   // Error - Can't add Number to what could be Integer
test2.add(new Object()); // Error - Can't add Object to what could be Integer

Debido a que los genéricos de Java son invariantes, los tipos deben coincidir exactamente cuando se trata de parámetros de tipo, por lo que los casos similares para ListListtodos fallan para compilar.

// My assumption of how your ArrayListList is defined.
class ArrayListList<E> extends ArrayList<List<E>> implements ListList<E> {}

ListList<? super Integer> llOfSuperI = new ArrayListList<>();
llOfSuperI.add(new ArrayList<Integer>());  // capture fails to match Integer
llOfSuperI.add(new ArrayList<Number>());   // capture fails to match Number
llOfSuperI.add(new ArrayList<Object>());   // capture fails to match Object

Sin embargo, una Listde Listlas compilaciones con los 3 casos.

List<List<? super Integer>> lOfLOfSuperI = new ArrayList<>();
lOfLOfSuperI.add(new ArrayList<Integer>());  // no capture; compiles
lOfLOfSuperI.add(new ArrayList<Number>());   // no capture; compiles
lOfLOfSuperI.add(new ArrayList<Object>());   // no capture; compiles

Su ListListes un tipo diferente de una Listde Lists, pero el diferente comportamiento de los genéricos en el que el parámetro de tipo se define significa que hay diferentes comportamientos genéricos. Es por esto que no se puede asignar directamente una ListList<? super T>a una List<List<? super T>>(1.1), y también por qué no puede echarlo (2). Puede convertirse a un tipo de prima para que se compile (3), pero que introduce la posibilidad de ClassCastException, en uso futuro del objeto fundido; eso es lo que el aviso se trata. Se pueden asignar a un List<? extends List<? super T>>(1), la introducción de otro comodín para capturar una relación subtipo, pero que introduce un comodín para ser capturado; usted no será capaz de añadir nada útil a esa lista.

Estas diferencias han surgido sólo porque introduce un comodín Comodín capturar y las diferencias asociadas. Sin utilizar un comodín, una ListList<E>es equivalente a una List<List<E>>y como se muestra en la parte superior de esta respuesta, no muestra problemas al compilar el código.

Si desea que todos los sub-listas para utilizar el mismo parámetro de tipo exacta, a continuación, seguir adelante y utilizar su ListListinterfaz, pero no use ningún comodín. Esto obliga exactamente el mismo tipo de parámetros en todas las listas que se agregan a su ListList, es decir, un ListList<Integer>sólo puede contener List<Integer>s.

Si desea que todos los sub-listas simplemente concuerda con un comodín, por ejemplo, contener una List<Number>, List<Integer>y List<Object>en la misma lista, a continuación, sólo tiene que utilizar una List<List<? super T>>para evitar la captura de comodín.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=226379&siteId=1
Recomendado
Clasificación