java - descargar - Manera correcta de implementar es igual a contrato
java offline (4)
Esta pregunta ya tiene una respuesta aquí:
Tengo un objeto de dominio llamado Usuario . Las propiedades del usuario incluyen ssoId, nombre, correo electrónico, createdBy, createdDate y userRole. De estos, ssoId debe ser único en el sentido de que no hay dos usuarios que puedan tener la misma id. Así que mi método igual verifica el id de 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 de negocios. La implementación anterior devolverá true para dos objetos con el mismo ID de sso pero con valores diferentes para, por ejemplo, nombre, correo electrónico o ambos. ¿Debo cambiar mi contrato de igualdad para verificar la igualdad de todos los campos? ¿Cuál es tu sugerencia?
Esta es una decisión difícil de hacer.
Este es un lugar en el que me metí al considerar el hash hace unos meses. Le sugiero que lea 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 de todo el objeto ... también podría incluir información de auditoría allí.
El hecho es que ''igual'' tiene muchos significados posibles.
Resolví esto implementando igual como una igualdad estricta en todos los campos, simplemente porque después de preguntar alrededor parece ser el significado intuitivo de iguales. Luego construí methos para los otros tipos de igualdad que requerí y definí una interfaz para envolverlos.
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 direcciones de memoria diferentes.
Esto es (casi) correcto para la "igualdad técnica", pero no para la "igualdad natural". Para lograr la máxima igualdad técnica, también debe probar el reflejo de o == this
. Puede suceder que el objeto aún no se haya conservado en la base de datos y, por lo tanto, aún no tenga una identificación 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 caro) 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 un poco decente (Eclipse, Netbeans, etc.) simplemente puede autogenerar equals()
, hashCode()
(y también toString()
, getters y setters) para usted. Aprovecha de ello. En Eclipse, haga clic con el botón derecho y eche un vistazo a la opción de menú Fuente (Alt + Shift + S).
Ver también:
Lo que estás haciendo parece estar bien, y no estás violando ninguna de las reglas que los equals
deben seguir.
Es posible que aún desee verificar otros campos, no para cambiar la semántica de los equals
, sino para detectar una inconsistencia en su lógica de negocios y posiblemente desencadenar una aserción / excepción.
Si en su modelo, ssoid debe ser único, eso implica que los valores para los otros campos no deben ser diferentes para dos instancias de Usuario. Si desea validar esa suposición, puede hacerlo con aseveraciones dentro del método igual si la sobrecarga no es un problema.