¿El uso de la Clase como clave para un HashMap causa efectos indeseables?

Maarten:

Considera lo siguiente:

Map<Class<?>, Object> myMap = new HashMap<Class<?>, Object>();
Foo fooObject = New Foo();
myMap.put(fooObject.getClass(), fooObject)

Tenga en cuenta que java.lang.Class no implementa el método hashCode () en sí, sino que hereda de java.lang.Object implícita. He verificado esto en JDK 1.8.

Es java.lang.Classseguro de usar como clave para una java.util.HashMap? Será myMap.get(Foo.class)siempre volver a los valores que puse como myMap.put(fooObject.getClass(), fooObject)? Considere el software para tener varios cargadores de clases y mecanismos de serialización. ¿Seguirá siendo el mismo resultado? Si no es así ... ¿Cuál sería una alternativa?

Stephen C:

Es seguro java.lang.Class utilizar como clave para una java.util.HashMap?

Si.

Voluntad myMap.get (Foo.class) siempre devuelven los valores que puse como myMap.put (fooObject.getClass (), fooObject)?

Si.

El uso de un Classobjeto como una llave en una HashMapes seguro. La Classclase hereda el Object::equalsy Object::hashCodemétodos. Por lo tanto equalspara Classobjetos está poniendo a prueba la identidad del objeto.

Esta es la semántica correcta para la igualdad tipo en Java. La aplicación de las ClassLoader::defineClassasegura método que nunca se puede obtener dos diferentes Classobjetos que representan el mismo tipo Java.

Sin embargo, hay una arruga. La especificación del lenguaje Java ( JLS 4.3.4 ) establece lo siguiente:

En tiempo de ejecución, varios tipos de referencia con el mismo nombre binario pueden ser cargados simultáneamente por diferentes cargadores de clases. Estos tipos pueden o no representar la misma declaración de tipo. Incluso si dos de estos tipos representan la misma declaración de tipo, que se consideran diferentes.

(El nombre del archivo binario está relacionado con el nombre de dominio completo de un tipo llamado, y tiene en cuenta las clases anónimas, y los tipos de matriz.)

Lo que esto significa es que si (con éxito) de llamada ClassLoader::defineClasspara las clases con el mismo nombre totalmente calificado con dos cargadores de clases diferentes, obtendrá diferentes tipos de Java. Independientemente de los códigos de bytes que utilizó. Por otra parte, si se intenta molde de un tipo a otro, obtendrá una excepción de difusión clase.


Ahora la pregunta es qué este asunto en su caso de uso?

Respuesta: Probablemente no.

  • A menos que usted (o su marco) está haciendo las cosas difíciles con cargadores de clases, no se plantea la situación.

  • Si lo hace, entonces es probable que tenga los dos tipos (con el mismo nombre de dominio completo y cargadores de clases diferentes) para tener las diferentes entradas en el HashMap. (Debido a que los tipos son diferentes!)

  • Pero si usted necesita los dos tipos de tener la misma entrada, entonces se puede usar el nombre completo de la clase como la clave, que se puede obtener utilizando Class::getCanonicalName. Si tiene que hacer frente a las clases de matriz, etc, a continuación, utilizar Class::getNamelo que devuelve el nombre del archivo binario para el tipo.


¿Qué pasa con los mecanismos de serialización?

Un Classobjeto no puede ser serializado usando serialización de objetos, ya que Classno implementa Serializable. Si implementa / utilizar algún otro mecanismo de serialización que es compatible con la serialización de Classobjetos, a continuación, que las necesidades mecanismo sea compatible con JLS 4.3.4.

Supongo que te gusta

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