[En el momento de escribir este artículo, se publicaron otras tres respuestas].
Para reiterar, el objetivo de mi pregunta es encontrar casos estándar de pruebas para confirmar que hashCodey equalsestán de acuerdo entre sí. Mi enfoque para esta pregunta es imaginar los caminos comunes que toman los programadores al escribir las clases en cuestión, es decir, datos inmutables. Por ejemplo:
- Escribió
equals()sin escribir hashCode(). Esto a menudo significa que la igualdad se definió como la igualdad de los campos de dos instancias.
- Escribió
hashCode()sin escribir equals(). Esto puede significar que el programador buscaba un algoritmo hash más eficiente.
En el caso del # 2, el problema me parece inexistente. No se han realizado instancias adicionales equals(), por lo que no se requieren instancias adicionales para tener códigos hash iguales. En el peor de los casos, el algoritmo hash puede producir un rendimiento más deficiente para los mapas hash, lo que está fuera del alcance de esta pregunta.
En el caso del # 1, la prueba unitaria estándar implica la creación de dos instancias del mismo objeto con los mismos datos pasados al constructor y la verificación de códigos hash iguales. ¿Qué pasa con los falsos positivos? Es posible elegir los parámetros del constructor que dan como resultado códigos hash iguales en un algoritmo que, sin embargo, no es sólido. Una prueba unitaria que tiende a evitar tales parámetros cumpliría el espíritu de esta pregunta. El atajo aquí es inspeccionar el código fuente equals(), pensar detenidamente y escribir una prueba basada en eso, pero si bien esto puede ser necesario en algunos casos, también puede haber pruebas comunes que detectan problemas comunes, y tales pruebas también cumplen con el espíritu de esta pregunta.
Por ejemplo, si la clase que se va a probar (llamémosla Datos) tiene un constructor que toma un String, y las instancias construidas a partir de Strings son equals()instancias que lo fueron equals(), entonces una buena prueba probablemente probaría:
new Data("foo")
- otro
new Data("foo")
Incluso podríamos verificar el código hash para new Data(new String("foo"))obligar a la cadena a no ser internada, aunque es más probable que produzca un código hash correcto que Data.equals()un resultado correcto, en mi opinión.
La respuesta de Eli Courtwright es un ejemplo de pensar mucho en una forma de romper el algoritmo hash basado en el conocimiento de la equalsespecificación. El ejemplo de una colección especial es bueno, ya Collectionque los mensajes de correo electrónico creados por el usuario aparecen a veces y son bastante propensos a fallar en el algoritmo hash.