ProgramaciónDesarrollador Java

Explique las características del método equals() en Java: cuándo y por qué sobrescribirlo, cómo implementarlo correctamente y qué problemas pueden surgir por su uso incorrecto.

Supere entrevistas con el asistente de IA Hintsage

Respuesta

El método equals() determina si dos objetos se consideran "iguales". Por defecto, compara referencias (es decir, ==), pero a menudo las clases (por ejemplo, entidades, objetos de valor) requieren comparación lógica basada en datos.

Cuándo sobrescribir:

  • Si la identidad lógica de los objetos es importante para su clase (por ejemplo, dos usuarios con el mismo correo electrónico son "el mismo usuario")
  • Si el objeto se almacenará en colecciones (por ejemplo, HashSet), que utilizan equals (y hashCode)

Requisitos:

  • Equals debe ser reflexivo, simétrico, transitivo, consistente y para cualquier x no nulo, x.equals(null) debe ser false
  • Al sobrescribir equals, ¡es OBLIGATORIO sobrescribir hashCode!

Ejemplo:

public class Person { private String email; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(email, person.email); } @Override public int hashCode() { return Objects.hash(email); } }

Pregunta capciosa

Si dos objetos son iguales según equals(), ¿deben tener siempre el mismo hashCode()?

Respuesta: ¡Sí! Este es un requisito de los contratos de Java. Pero lo contrario no es cierto: dos objetos con el mismo hashCode pueden no ser iguales según equals()— los códigos hash pueden coincidir para diferentes objetos (colisiones).

Ejemplo de error:

person1.equals(person2); // true person1.hashCode() != person2.hashCode(); // ¡Error!

Ejemplos de errores reales por desconocimiento de los detalles del tema


Historia

En una aplicación corporativa, la entidad Usuario se insertó en un HashSet. Equals fue sobrescrito, hashCode no. Después de modificar los campos que afectan equals, HashSet "perdió" este objeto: una búsqueda con el método contains devolvía false, incluso para los mismos datos.


Historia

En un proyecto de IoT, las entidades temporalmente se compararon solo por id, y luego se cambió la lógica a equals considerando el nombre. HashMap empezó a comportarse de forma impredecible, al actualizar las claves aparecieron duplicados— se violó el contrato equals/hashCode debido a la mezcla de versiones de implementación.


Historia

Al desarrollar una API para comparar pedidos, dos clases diferentes implementaron su equals, una de ellas llamaba a getClass(), y la otra— instanceof. Esto llevó a una comparación no simétrica de los pedidos y errores al usar colecciones y lógica de negocio.