¿Cuáles son las razones por las que Map.get (clave de objeto) no es (totalmente) genérico?
¿Cuáles son las razones detrás de la decisión de no tener un método get completamente genérico en la interfaz de java.util.Map<K, V>
.
Para aclarar la pregunta, la firma del método es
V get(Object key)
en lugar de
V get(K key)
y me pregunto por qué (lo mismo para remove, containsKey, containsValue
).
Como lo mencionaron otros, la razón por la cual get()
, etc. no es genérica porque la clave de la entrada que está recuperando no tiene que ser del mismo tipo que el objeto al que le pasa get()
; la especificación del método sólo requiere que sean iguales. Esto se desprende de cómo el equals()
método toma un Objeto como parámetro, no solo el mismo tipo que el objeto.
Aunque puede ser cierto que muchas clases se han equals()
definido de modo que sus objetos sólo puedan ser iguales a los objetos de su propia clase, hay muchos lugares en Java donde este no es el caso. Por ejemplo, la especificación para List.equals()
dice que dos objetos Lista son iguales si ambos son Listas y tienen el mismo contenido, incluso si son implementaciones diferentes de List
. Entonces, volviendo al ejemplo de esta pregunta, de acuerdo con la especificación del método, es posible tener un Map<ArrayList, Something>
y para mí llamar get()
con un LinkedList
argumento as, y debería recuperar la clave, que es una lista con el mismo contenido. Esto no sería posible si get()
fuera genérico y restringiera su tipo de argumento.
Un increíble codificador de Java en Google, Kevin Bourrillion, escribió exactamente sobre este tema en una publicación de blog hace un tiempo (ciertamente en el contexto de Set
en lugar de Map
). La frase más relevante:
De manera uniforme, los métodos del Marco de Colecciones de Java (y también de la Biblioteca de Colecciones de Google) nunca restringen los tipos de sus parámetros, excepto cuando es necesario para evitar que la colección se rompa.
No estoy completamente seguro de estar de acuerdo con esto como principio (por ejemplo, .NET parece estar bien al requerir el tipo de clave correcto), pero vale la pena seguir el razonamiento en la publicación del blog. (Habiendo mencionado .NET, vale la pena explicar que parte de la razón por la cual no es un problema en .NET es que existe el problema más grande en .NET de una variación más limitada...)