Puntos a tocar en esta publicación:
- Sobrescribiendo el método equals
- Reglas que sigue el método equals
- Ojo, mucho ojo.
- Sobrescribiendo el método hashCode
- ¿Que implica el hashcode?
- Reglas que sigue el método hashCode
- Ojo, mucho ojo.
Indagando en la javadoc acerca del método equals(Object o), podemos encontrar lo siguiente:
Método: equals(Object o)
Valor de retorno : boolean
Descripción: Indica si un objeto es igual a este.
Este método lo utilizamos para saber si un objeto es igual que otro. Este método utiliza el operador == para comparar a dos objetos y decidir si son iguales, por ejemplo podemos tener la siguiente clase:
public class Demo {
private int boleta;
public Demo(int boleta){
this.boleta = boleta;
}
public int getBoleta(){
return this.boleta;
}
public static void main(String[] args) {
Demo demoA = new Demo(20);
Demo demoB = new Demo(20);
System.out.println(demoA.equals(demoB));
}
}
@Override
public boolean equals(Object o){
if(( o instanceof Demo) && (((Demo)o).getBoleta() == this.boleta))
{
return true;
}else{
return false;
}
}
public static void main(String[] args) {
Demo demoA = new Demo(20);
Demo demoB = new Demo(20);
System.out.println(demoA.equals(demoB));
}
Por lo anterior, esta ejecución del método main, nos dará como resultado un true en la salida por consola.
Reglas que sigue el método equals
- Reflexivo: Para cualquier referencia al valor x, x.equals(x) debe regresar true.
- Simetrico: Para cualquier referencia a los valores x y z, x.equals(z) debe regresar true si y solo si z.equals(x) es true.
- Transitivo. Para cualquier referencia a los valores w, x y z, si w.equals(x) regresa true y x.equals(z) regresa true, entonces w.equals(z) debe regresar true.
- Consistente: Para cualquier referencia a los valores x y z, múltiples invocaciones a x.equals(z) consistentemente regresaran true o false, si es que los valores utilizados para la comparación de los objetos no ha sido modificada.
- Para cualquier referencia no nula al valor x, x.equals(null), debe regresar false.
Ojo, mucho ojo
- Asegúrate de sobrescribir el método equals. Las siguientes son implementaciones del método equals que son validas para el compilador, pero no validas para sobrescribir el método:
- boolean equals(Objeto o). Esta implementación no sobreescribe el método equals de la clase Object, ya que el método debe ser declarado como public.
- public boolean equals(Demo o). Esta implementación no sobreescribe el método equals de la clase Object, ya que el parámetro que necesita el método equals debe ser explícitamente un objeto de la clase Object, y no uno que extienda de éste. Esta implementación, al igual que la anterior es una sobrecarga del método equals, mas no sobreescribe este método.
La descripción correcta del método equals, es decir, la forma en como debe sobrescribirse es la siguiente:
public boolean equals(Objeto o);
¿Qué implica el hashcode?
public class Demo {
private int boleta;
public Demo(int boleta){
this.boleta = boleta;
}
public int getBoleta(){
return this.boleta;
}
@Override
public boolean equals(Object o){
if((o instanceof Demo) && (((Demo)o).getBoleta()== this.boleta))
{
return true;
}else{
return false;
}
}
public static void main(String[] args) {
Demo demoA = new Demo(20);
Demo demoB = new Demo(20);
System.out.println(demoA.equals(demoB));
System.out.println(demoA.hashCode());
System.out.println(demoB.hashCode());
}
}
Esto nos da como resultado:
true
1414159026
1569228633
Sobrescribiendo el método hashCode
A continuación veremos como podremos sobrescribirlo:
@Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + this.boleta;
return hash;
}
La salida que obtenemos una vez que se rescribe este método en el ejemplo de arriba es :
true
699
699
lo que nos dice que estos métodos son iguales según equals, y que además tienen el mismo numero hashcode.
Reglas que sigue el método hashCode
- Si el método hashCode es invocado en múltiples ocasiones durante la ejecución de una aplicación, debe regresar consistentemente el mismo valor entero, esto si la información utilizada para calcular el hashcode no ha cambiado entre invocación e invocación del método hashCode.
- Si dos objetos son iguales según el método equals, entonces la llamada al método hashCode debe regresar el mismo hashcode.
- No es requerido que si dos métodos no son iguales según el método equals, tengan diferentes valores hashcode.
Ojo, mucho ojo
- Si dos métodos son iguales según el método equals, el método hashCode debe regresar el mismo entero para ambos métodos. Sin embargo, si el métodos equals dice que dos métodos no son iguales, el método hashCode puede o no regresar el mismo entero.
- Retornar un valor fijo en un método hashCode es una mala idea, ya que tendremos múltiples objetos con el mismo valor hashcode, lo cual no ayuda en nada a la hora de trabajar con colecciones de tipo Hash*.
- Si utilizamos variables de clase de tipo transient para generar un hashcode, serializamos el objeto en cuestión y queremos recuperar el hashcode de ese método, nos encontraremos con que el hashcode será diferente al hashcode con que se serializó el objeto. Ya que este tipo de variables no se serializa. Por eso es una mala idea utilizar variables transient para generar el hashcode.