¿Cuál es la diferencia entre el tipo de comodín ilimitado, la Lista Y la Lista de tipo sin formato?

¿Podrías ayudarme a entender la diferencia entre la lista de tipo comodín sin límites y la lista de tipo sin formato ?

List b; // unbounded wildcard type List a; // raw type 

Junto con esto, ¿alguien puede ayudarme a entender qué es una lista de parámetros de tipo delimitada ?

 List c; 

Aquí hay un resumen de los tres:

  • List : una lista sin parámetro de tipo. Es una lista cuyos elementos son de cualquier tipo; los elementos pueden ser de diferentes tipos .

  • List : Una lista con un parámetro de tipo ilimitado. Sus elementos son de un tipo específico, pero desconocido; los elementos deben ser todos del mismo tipo .

  • List : una lista con un parámetro de tipo llamado T El tipo suministrado para T debe ser de un tipo que se extiende E , o no es un tipo válido para el parámetro.

Deberías ver realmente Java efectivo, Artículo 23: No usar tipos brutos en el nuevo código.

Para usar el ejemplo de ese libro, considere el siguiente ejemplo … ¿qué sucede si tiene una colección en la que no le importa qué tipos de elementos contiene? Por ejemplo, desea ver cuántos elementos son comunes entre dos conjuntos. Puedes pensar en lo siguiente:

 public static int numElementsInCommon(Set s1, Set s2) { int result = 0; for (Object o : s1) { if (s2.contains(o)) { ++result; } } return result; } 

Este ejemplo, mientras funciona, no es una buena idea debido al uso de tipos sin procesar. Los tipos crudos simplemente no son seguros en absoluto … podrías terminar modificando el conjunto de una manera que no sea segura y corrompa tu progtwig. En su lugar, errar por el lado de la precaución y utilizar la alternativa tipo seguro:

 public static int numElementsInCommon(Set s1, Set s2) { int result = 0; for (Object o : s1) { if (s2.contains(o)) { ++result; } } return result; } 

La diferencia es que solo puede agregar null a un Set , Y NO PUEDE asumir nada sobre el elemento que saca de un Set . Si usa un Set sin Set , puede agregar cualquier cosa que desee. El método numElementsInCommon es un buen ejemplo donde ni siquiera necesita agregar nada y no necesita asumir nada sobre lo que está en el conjunto. Es por eso que es un buen candidato para usar el ? comodín.

Espero que esto ayude. Lea ese ítem completo en Java efectivo y realmente quedará claro.

Para responder la segunda parte de tu pregunta … ¿recuerdas que dije cuándo usaste el ? comodín, ¿no puedes asumir nada sobre el elemento que sacas del conjunto? ¿Qué sucede si necesita hacer una suposición sobre la interfaz del objeto que eliminó del conjunto? Por ejemplo, supongamos que desea realizar un seguimiento de un conjunto de cosas Cool .

 public interface Cool { // Reports why the object is cool void cool(); } 

Entonces podrías tener un código como este:

 public static void reportCoolness(Set s) { for (Object item : s) { Cool coolItem = (Cool) item; coolItem.cool(); } } 

Esto no es tipo seguro … necesitas asegurarte de pasar en un conjunto con solo objetos Cool . Para solucionarlo, puedes decir:

 public static void reportCoolness(Set s) { for (Cool coolItem : s) { coolItem.cool(); } } 

¡Esto es genial! Hace exactamente lo que quiere y es tipo seguro. Pero, ¿qué pasa si más tarde tienes esto?

 public interface ReallyCool extends Cool { // Reports why the object is beyond cool void reallyCool(); } 

Como todos los objetos de ReallyCool son Cool , debería poder hacer lo siguiente:

 Set s = new HashSet(); // populate s reportCoolness(s); 

Pero no se puede hacer eso porque los generics tienen la siguiente propiedad: supongamos que B es una subclase de A , luego Set NO es una subclase de Set . La charla técnica para esto es “Los tipos generics son invariables”. (A diferencia de la covariante).

Para que funcione el último ejemplo, necesitarás crear un Set al convertir (con seguridad) cada elemento en el Set . Para evitar que los clientes de tu API pasen por este código desagradable e innecesario, puedes hacer que el método de reportCoolness más flexible así:

 public static void reportCoolness(Set s) { for (Cool coolItem : s) { coolItem.cool(); } } 

Ahora su método toma cualquier Set que contenga elementos que sean Cool o cualquier subclase de Cool . Todos estos tipos se adhieren a la aplicación Cool … por lo que podemos llamar de forma segura al método cool() en cualquier elemento

¿Tener sentido? Espero que esto ayude.

En su primera pregunta, la diferencia entre List y List :

Una diferencia significativa entre los dos es que cuando tiene un comodín como tipo, el tipo de Collection es desconocido, por lo que el método add generará un error de tiempo de comstackción.

Aún puede obtener valores de la List , Pero necesita un lanzamiento explícito.