new linkedlist example java generics collections types unbounded-wildcard

java - linkedlist - ¿Cuál es la diferencia entre Colección<?> Y Colección<T>



list new arraylist java (4)

¿El que usa el comodín ilimitado (?) En realidad significa ? extends Object ? extends Object (cualquier cosa que amplíe el objeto).

Esto, en Java, implica una naturaleza de solo lectura, es decir, se nos permite leer elementos de la estructura genérica, pero no se nos permite devolver nada, ya que no podemos estar seguros del tipo real de los elementos en eso.

Por lo tanto, me atrevo a decir que es un enfoque muy válido en el método printCollection en discusión, al menos, hasta que nos encontramos con una situación en la que tenemos que asumir un tipo.

Si tuviera que elegir entre ellos dos, diría que el segundo (con el parámetro de tipo T) es un enfoque más limpio porque al menos puede suponer que la colección tiene un cierto tipo T , y que puede resultar útil en ciertos escenarios. .

Por ejemplo, si la Colección necesitaba estar sincronizada, simplemente podría hacer:

<T> void printCollection(Collection<T> c) { List<T> copy = new ArrayList<T>(); synchronized(c) { copy.addAll(c); } for (T e : copy) { System.out.println(e); } }

Creé muy fácilmente una nueva colección de tipo T y copio todos los elementos de la colección original en esta segunda. Esto lo puedo hacer, porque puedo asumir que el tipo de colección es T , ¿y no ? .

Por supuesto, podría hacer lo mismo con el primer método (usando el comodín de ubicación), pero no es tan limpio, tuve que hacer suposiciones de que el tipo de Colección es Objeto, ¿y no ? (que no se puede usar válidamente como argumento de tipo: new ArrayList<?>() ).

void printCollection(Collection<?> c) { List<Object> copy = new ArrayList<Object>(); synchronized(c) { copy.addAll(c); } for (Object e : copy) { System.out.println(e); } }

Soy principalmente un desarrollador de C # y le estaba enseñando Estructuras de datos a mi amigo, ellos usan Java en su universidad y vi una expresión de este tipo en Java:

void printCollection(Collection<?> c) { for (Object e : c) { System.out.println(e); } }

No he visto tal cosa en C #, así que me pregunto cuál es la diferencia entre Collection<T> y Collection<?> En Java.

void printCollection(Collection<T> c) { for (Object e : c) { System.out.println(e); } }

Creo que podría haber sido escrito en la forma anterior también. El tipo en la documentación estaba comparando la Collection<Object> y la Collection<T> sin embargo.

Los ejemplos se toman de http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html


Con la Collection<T> podrías hacer

void printCollection(Collection<T> c) { for (T e : c) { System.out.println(e); } }

Con Collection<?> Solo sabes que la colección contiene objetos.


La declaración Collection<?> (Pronunciada como "collection of unknown") es una colección cuyo tipo de elemento coincide con cualquier cosa, mientras que Collection<T> representa una colección de tipo T

Como es habitual, las preguntas frecuentes de Angelika Langer sobre genéricos tienen una extensa discusión sobre el tema, una lectura obligatoria para comprender completamente todo sobre genéricos en Java, y comodines ilimitados (el tema de esta pregunta) en particular. Citando de las preguntas frecuentes:

El comodín ilimitado se ve como "?" Y representa la familia de todos los tipos. El comodín ilimitado se utiliza como argumento para las instancias de tipos genéricos. El comodín ilimitado es útil en situaciones en las que no es necesario conocer el argumento de tipo de un tipo parametrizado

Para obtener más detalles técnicos, consulte la sección §4.5.1 Argumentos de tipo y comodines de la especificación del lenguaje Java , que establece que:

Los argumentos de tipo pueden ser tipos de referencia o comodines. Los comodines son útiles en situaciones donde solo se requiere un conocimiento parcial sobre el parámetro de tipo.


Collection<?> Es una colección de parámetros de tipo desconocido.

En lo que respecta a la persona que llama, no hay diferencia entre

void printCollection(Collection<?> c) { ... }

y

<T> void printCollection(Collection<T> c) { ... }

Sin embargo, este último permite que la implementación haga referencia al parámetro de tipo de la colección y, por lo tanto, a menudo se prefiere.

La sintaxis anterior existe porque no siempre es posible introducir un parámetro de tipo en el ámbito adecuado. Por ejemplo, considere:

List<Set<?>> sets = new ArrayList<>(); sets.add(new HashSet<String>()); sets.add(new HashSet<Integer>());

Si tuviera que reemplazar ? por algún tipo de parámetro T , todos los conjuntos en sets se restringirían al mismo tipo de componente, es decir, ya no puedo colocar conjuntos con diferentes tipos de elementos en la misma lista, como lo demuestra el siguiente intento:

class C<T extends String> { List<Set<T>> sets = new ArrayList<>(); public C() { sets.add(new HashSet<String>()); // does not compile sets.add(new HashSet<Integer>()); // does not compile } }