2010-06-06 12 views
10

Estoy intentando algún código sobre la igualdad de objetos en java. Como he leído en algún lugar¿Por qué hashCode() devuelve el mismo valor para un objeto en todas las ejecuciones consecutivas?

hashCode() es un número que se genera aplicando la función hash. La función hash puede ser diferente para cada objeto pero también puede ser la misma. En el nivel de objeto, devuelve la dirección de memoria del objeto.

Ahora, tengo el programa de ejemplo, que corro 10 veces, consecutivamente. Cada vez que ejecuto el programa obtengo el mismo valor que el código hash.

Si la función hashCode() devuelve la ubicación de la memoria para el objeto, ¿cómo es que la java (JVM) almacena el objeto en la misma dirección de memoria en las ejecuciones consecutivas?

¿Puede darme alguna idea y su opinión sobre este tema?

El Programa Me postulo para probar este comportamiento es el siguiente:

public class EqualityIndex { 

    private int index; 

    public EqualityIndex(int initialIndex) { 
     this.index = initialIndex; 
    } 

    public static void main(String[] args) { 
     EqualityIndex ei = new EqualityIndex(2); 
     System.out.println(ei.hashCode()); 
    } 

} 

Cada vez que ejecute este programa, el valor de código hash devuelto es 4072869.

+0

¿Cuáles son sus objetos? Muestra un código – Bozho

+0

¿está seguro de que su valor es una dirección de memoria? ¿Puedes publicarlo? – vodkhang

+1

El '.hashCode()' predeterminado de Java es en realidad más un identificador * de memoria incremental * que * dirección *, por lo que, naturalmente, cuando las condiciones previas son las mismas, también lo es el resultado. – Esko

Respuesta

14

¿cómo es que el java (JVM) almacena el objeto en la misma dirección de memoria en las ejecuciones consecutivas?

¿Por qué no? Los programas que no son kernel nunca funcionan con direcciones de memoria absolutas, usan memoria virtual donde cada proceso obtiene su propio espacio de direcciones. Por lo tanto, no sorprende que un programa determinista coloque cosas en la misma ubicación en cada ejecución.

+0

Vale la pena señalar que esta respuesta no se aplica a las JVM modernas. Por ejemplo, por defecto, 'Object.hashCode()' de JDK7 no usa la dirección del objeto ** en absoluto **. Ver http://stackoverflow.com/questions/13860194/what-is-anternal-address-in-java/13860488#13860488 – NPE

2

¿Qué tipo de objeto se ha creado? Es un tipo específico de objeto como Cadena (por ejemplo). Si es un tipo específico, la clase ya puede anular el método hashCode() y devolvérselo. En ese caso, lo que recibe ya no es una dirección de memoria.

y también qué valores recibe, ¿está seguro de si es la dirección de memoria?

Así que, por favor, puesto más código para más detalles

3

Bueno, los objetos pueden muy bien terminar en el mismo lugar en la memoria virtual. Nada en contra de eso. La conclusión es que no deberías preocuparte de ninguna manera. Si hashCode se implementa para devolver algo relacionado con la dirección de almacenamiento interno (¡no hay ninguna garantía!) No hay nada útil que pueda hacer con esa información de todos modos.

1

hashCode puede y puede ser anulado por la clase que está utilizando, the JavaDoc for Object.hashCode() indica que '... normalmente se implementa convirtiendo la dirección interna del objeto en un número entero ...' por lo que la implementación real puede ser un sistema dependiente. Tenga en cuenta también el tercer punto en el JavaDoc de que dos objetos que no son iguales no son necesarios para devolver diferentes hashCodes.

0

Si dos objetos son iguales, deben tener los mismos códigos hash. Por lo tanto, siempre que no cree instancias simples Object, cada vez que cree un objeto que tenga el mismo valor, obtendrá el mismo código hash.

+0

no siempre es verdad. Depende de la clase de la que estés hablando. Es una buena convención anular siempre equals y hashCode, pero no siempre es cierto – vodkhang

+0

Por supuesto, si los objetos son comparables. –

+0

Cuando dice "tengo que tener", realmente quiere decir "debería tener". No hay nada en el lenguaje o sistema de tiempo de ejecución que * evite * que usted corte el contrato para 'hashcode()' y 'equals()'. Pero si lo hace, cualquier cosa que use hash en su objeto se comportará de forma incorrecta. –

1
for (int i=0; i < 10; i++) { 
    System.out.println("i: " + i + ", hashCode: " + new Object().hashCode()); 
} 

impresiones:


i: 0, hashCode: 1476323068 
i: 1, hashCode: 535746438 
i: 2, hashCode: 2038935242 
i: 3, hashCode: 988057115 
i: 4, hashCode: 1932373201 
i: 5, hashCode: 1001195626 
i: 6, hashCode: 1560511937 
i: 7, hashCode: 306344348 
i: 8, hashCode: 1211154977 
i: 9, hashCode: 2031692173 
+0

Interesante. ¿Qué JVM estás usando? –

+0

java -version: versión java "1.6.0_20" Java (TM) SE Runtime Environment (compilación 1.6.0_20-b02) Java HotSpot (TM) 64-Bit Server VM (compilación 16.3-b01, modo mixto) –

2

Como he leído en alguna parte: "... En el nivel de objeto, devuelve la dirección de memoria del objeto."

Esa declaración es incorrecta, o en el mejor de los casos, una simplificación excesiva.

La declaración se refiere a la implementación predeterminada de Object.hashCode() que devuelve el mismo valor que System.identityHashcode(Object).

El Javadoc para Object.hashCode() dice esto:

Tanto como sea razonablemente práctico, el método hashCode definido por la clase Object no devolver enteros distintos de objetos distintos. (Esto se implementa típicamente mediante la conversión de la dirección interna del objeto en un entero, pero esta técnica de implementación no es requerida por el lenguaje de programación Java ™.)

y esto:

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 la información utilizada en comparaciones iguales en el objeto.

De hecho, el valor de código hash identidad se basa generalmente en la dirección de la máquina del objeto cuando el método es llamado por primera vez para el objeto. El valor se almacena en un campo oculto en el encabezado Objeto. Esto permite que se devuelva el mismo código hash en llamadas posteriores ... incluso si el GC ha reubicado el objeto mientras tanto.

Tenga en cuenta que si el valor de código hash identidad cambió durante el tiempo de vida de un objeto, se violaría el contrato para hashcode(), y sería inútil como un código hash.

3

La función hashCode() debe devolver el mismo valor para el mismo objeto en la misma ejecución. No es necesario devolver el mismo valor para una ejecución diferente. Vea los siguientes comentarios que se extrajeron de la clase Object.

El contrato general de hashCode es:

Siempre 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 hay que volver constantemente el mismo entero, siempre que no la información utilizada en comparaciones iguales en el objeto se modifica. Este número entero no necesita permanecer constante desde una ejecución de una aplicación a otra ejecución de la misma aplicación.

He ejecutado su código algunas veces. Aquí está mi resultado

1935465023

1935465023

1935465023

1935465023

1935465023

1935465023

El mismo número se repite varias veces. Pero eso no quiere decir que siempre sean iguales. Supongamos, una implementación particular de JVM está buscando la primera ranura libre en la memoria. luego, si no ejecuta ninguna otra aplicación, las posibilidades de asignar el objeto en la misma ranura son altas.

Cuestiones relacionadas