@erickson es más o menos correcto. El código hash devuelto por java.lang.Object.hashCode()
no cambia durante la vida del objeto.
La forma en que esto se implementa (típicamente) es bastante inteligente. Cuando un objeto es reubicado por el recolector de basura, su hashcode original debe almacenarse en algún lugar en caso de que se vuelva a utilizar. La forma obvia de implementar esto sería agregar un campo de 32 bits al encabezado del objeto para contener el código hash. Pero eso agregaría una sobrecarga de 1 palabra a cada objeto, y desperdiciaría espacio en el caso más común ... donde no se llama al método hashCode
de un Objeto.
La solución es agregar dos bits de marca a la palabra de bandera del objeto y usarlos (más o menos) de la siguiente manera. El primer indicador se establece cuando se llama al método hashCode
. Una segunda bandera le dice al método hashCode
si usar la dirección actual del objeto como código hash, o usar un valor almacenado. Cuando el GC se ejecuta y reubica un objeto, prueba estos indicadores. Si se establece el primer indicador y el segundo no está configurado, el GC asigna una palabra adicional al final del objeto y almacena la ubicación del objeto original en esa palabra. Luego establece las dos banderas. A partir de ese momento, el método hashCode
obtiene el valor de código hash de la palabra al final del objeto.
De hecho, un identityHashCode
aplicación tiene que comportarse de esta manera a satisfacer la siguiente parte de la general hashCode contract:
"Cada vez que se invoca en el mismo objeto más de una vez durante una ejecución de una aplicación Java, el método hashCode debe devolver consistentemente el mismo entero, siempre que no se modifique ninguna información utilizada en comparaciones iguales en el objeto. Este número entero no necesita ser consistente desde una ejecución de una aplicación a otra ejecución de la misma aplicación ".
Una aplicación hipotética de identityHashCode()
que simplemente devuelve la dirección de la máquina actual de un objeto violaría la parte resaltada si/cuando el GC se trasladó el objeto a una dirección diferente. La única forma de evitar esto sería que la JVM (hipotética) garantice que un objeto nunca se mueve una vez que se ha invocado hashCode
. Y eso llevaría a problemas serios e intratables con la fragmentación del montón.
Si imprime el valor de algunos 'Object.hashCode's, probablemente notará que es poco probable que sean direcciones. Números impares en cualquier implementación razonable, por ejemplo. –