La forma correcta de implementar es igual a contrato

Tengo un objeto de dominio llamado Usuario . Las propiedades del usuario incluyen ssoId, name, email, createdBy, createdDate y userRole. De estos, ssoId debe ser único en el sentido de que ninguno de los dos usuarios puede tener el mismo ID sso. Entonces mi método equals verifica la identidad del sso y devuelve verdadero o falso.

@Override public boolean equals(Object o) { if (!(o instanceof User)) return false; return user.getSsoId().equals((User)o.getSsoId()); } 

Lo que siento es que esta es una implementación incorrecta, aunque es correcta en lo que respecta a las reglas comerciales. La implementación anterior devolverá true para dos objetos con la misma identificación sso pero con diferentes valores para decir nombre o correo electrónico o ambos. ¿Debo cambiar mi contrato de igualdad para verificar la igualdad de todos los campos? ¿Cuál es tu sugerencia?

Esto es (casi) correcto para “igualdad técnica”, pero no para “igualdad natural”. Para lograr la máxima igualdad técnica, también debe probar el reflexivo o == this . Puede suceder que el objeto no se conserve aún en DB y, por lo tanto, todavía no tenga una ID técnica. P.ej

 public class User { private Long id; @Override public boolean equals(Object object) { return (object instanceof User) && (id != null) ? id.equals(((User) object).id) : (object == this); } @Override public int hashCode() { return (id != null) ? (User.class.hashCode() + id.hashCode()) : super.hashCode(); } } 

Para la “igualdad natural”, debería comparar todas las propiedades no técnicas. Para las “entidades del mundo real” esto es, después de todo, más robusto (pero también más costoso) que la igualdad técnica.

 public class User { private String name; private Date birth; private int housenumber; private long phonenumber; @Override public boolean equals(Object object) { // Basic checks. if (object == this) return true; if (!(object instanceof User)) return false; // Property checks. User other = (User) object; return Objects.equals(name, other.name) && Objects.equals(birth, other.birth) && (housenumber == other.housenumber) && (phonenumber == other.phonenumber); } @Override public int hashCode() { return Objects.hash(name, birth, housenumber, phonenumber); } } 

Es cierto, eso es mucho código cuando hay muchas propiedades. Un IDE poco decente (Eclipse, Netbeans, etc.) puede autogenerar equals() , hashCode() (y también toString() , getters y setters) para usted. Toma ventaja de eso. En Eclipse, haga clic con el botón derecho en el código y observe la opción de menú Fuente (Alt + Mayúsculas + S).

Ver también:

  • JBoss: Equals y HashCode (en vista de la persistencia )
  • Hibernate: clases persistentes: implementación de equals () y hashCode ()
  • Pregunta SO relacionada: Reemplazar equals y hashCode en Java

Si en su modelo ssoid debe ser único, eso implica que los valores para los otros campos no deberían ser diferentes para dos instancias de Usuario. Si desea validar esa suposición, puede hacerlo con aserciones dentro del método equals si la sobrecarga no es un problema.

Lo que estás haciendo parece estar bien, y no estás violando ninguna de las reglas que deben seguir.

Es posible que desee verificar otros campos, no cambiar la semántica de equals , sino detectar una incoherencia en su lógica comercial y posiblemente desencadenar una aseveración / excepción.

Esta es una decisión difícil de tomar.

Este es un lugar en el que me metí cuando pensé en hacer hash hace unos meses. Le sugiero que lea sobre lo que es un hash porque es muy relevante para su respuesta … sugiero que esté buscando implementar algún tipo de hash y probar su igualdad.

Hay diferentes tipos de igualdad … existe la igualdad de la identidad del objeto, la igualdad de los datos del objeto, la igualdad del objeto completo … también puede incluir información de auditoría allí.

El hecho es que ‘igual’ tiene muchos significados posibles.

Resolví esto implementando igual igualdad estricta en todos los campos simplemente porque después de preguntar parece ser el significado intuitivo de los iguales. Luego construí methos para los otros tipos de igualdad que requería y definí una interfaz para ajustarlos.

No probaría la igualdad en el objeto == esto porque a menudo estás probando dos objetos diferentes con los mismos datos que en mi libro son iguales a pesar de que se refieren a diferentes direcciones de memoria.