Estoy usando Eclipse para ayudarme a limpiar algo de código para usar los genéricos de Java correctamente. La mayoría de las veces está haciendo un excelente trabajo de inferir tipos, pero hay algunos casos en los que el tipo inferido tiene que ser lo más genérico posible: Objeto. Pero Eclipse parece estar dándome una opción para elegir entre un tipo de Objeto y un tipo de '?'.
Entonces, ¿cuál es la diferencia entre:
HashMap<String, ?> hash1;
y
HashMap<String, Object> hash2;
Respuestas:
Una instancia de
HashMap<String, String>
partidosMap<String, ?>
pero noMap<String, Object>
. Digamos que desea escribir un método que acepte mapas deString
s a cualquier cosa: si pudiera escribirno puedes suministrar a
HashMap<String, String>
. Si tú escribes¡funciona!
Una cosa a veces mal entendida en los genéricos de Java es que
List<String>
no es un subtipo deList<Object>
. (Pero,String[]
de hecho, es un subtipo deObject[]
, esa es una de las razones por las que los genéricos y las matrices no se mezclan bien. (Las matrices en Java son covariantes, los genéricos no lo son, son invariantes )).Muestra: si desea escribir un método que acepte
List
s deInputStream
sy subtipos deInputStream
, escribiríaPor cierto: Java eficaz de Joshua Bloch es un excelente recurso cuando desea comprender las cosas no tan simples en Java. (Su pregunta anterior también se cubre muy bien en el libro).
fuente
Otra forma de pensar sobre este problema es que
es equivalente a
Combine este conocimiento con el "Principio Get and Put" en la sección (2.4) de Java Generics and Collections :
y el comodín puede comenzar a tener más sentido, con suerte.
fuente
HashMap<String, ? extends Object>
así que solo evitanull
que se agregue en el hashmap?Es fácil de entender si recuerda que
Collection<Object>
es solo una colección genérica que contiene objetos de tipoObject
, peroCollection<?>
es un súper tipo de todos los tipos de colecciones.fuente
Las respuestas anteriores a la covarianza cubren la mayoría de los casos, pero pierden una cosa:
"?" incluye "Objeto" en la jerarquía de clases. Se podría decir que String es un tipo de objeto y Object es un tipo de?. ¿No todo coincide con el objeto, pero todo coincide?
fuente
No puede poner nada con seguridad
Map<String, ?>
, porque no sabe de qué tipo se supone que son los valores.Puede poner cualquier objeto en a
Map<String, Object>
, porque se sabe que el valor es unObject
.fuente
Map<String,Integer>
. Solo losInteger
objetos deben colocarse almacenados en el mapa como valores. Pero ya que no se conoce el tipo del valor (es?
), no se sabe si si es seguro para llamarput(key, "x")
,put(key, 0)
o cualquier otra cosa.Declarar
hash1
como unHashMap<String, ?>
dictamen que la variablehash1
puede contener cualquieraHashMap
que tenga una claveString
y cualquier tipo de valor.Todo lo anterior es válido, porque la variable
map
puede almacenar cualquiera de esos mapas hash. A esa variable no le importa cuál es el tipo de Valor, del hashmap que contiene.Sin embargo, tener un comodín no le permite poner ningún tipo de objeto en su mapa. De hecho, con el mapa de hash anterior, no se puede agregar nada usando la
map
variable:Todas las llamadas a métodos anteriores generarán un error en tiempo de compilación porque Java no sabe cuál es el tipo de valor de HashMap en su interior
map
.Todavía puede obtener un valor del mapa hash. Aunque "no conoce el tipo de valor" (porque no sabe qué tipo de mapa hash está dentro de su variable), puede decir que todo es una subclase de
Object
y, por lo tanto, lo que sea que salga del mapa será del tipo Objeto:El bloque de código anterior imprimirá 10 en la consola.
Por lo tanto, para terminar, utilice un
HashMap
con comodines cuando no le importe (es decir, no importa) cuáles son los tipos deHashMap
, por ejemplo:De lo contrario, especifique los tipos que necesita:
En el método anterior, necesitaríamos saber que la clave del Mapa es a
Character
, de lo contrario, no sabríamos qué tipo usar para obtener valores de ella.toString()
Sin embargo, todos los objetos tienen un método, por lo que el mapa puede tener cualquier tipo de objeto para sus valores. Todavía podemos imprimir los valores.fuente