Me encontré con un problema interesante (y muy frustrante) con el equals()método hoy que causó el bloqueo de lo que pensé que era una clase bien probada y causó un error que me llevó mucho tiempo rastrear.
Solo para completar, no estaba usando un IDE o depurador, solo un buen editor de texto antiguo y System.out. El tiempo era muy limitado y era un proyecto escolar.
De todos modos
Que estaba desarrollando un carrito de la compra básica que podría contener un ArrayListde Booklos objetos . Con el fin de poner en práctica los addBook(), removeBook()y hasBook()métodos de la Cesta, quería comprobar si el Bookya existía en el Cart. Entonces me voy
public boolean equals(Book b) {
... // More code here - null checks
if (b.getID() == this.getID()) return true;
else return false;
}
Todo funciona bien en las pruebas. Creo 6 objetos y los lleno con datos. Realiza muchas operaciones de adición, eliminación, has () en Carty todo funciona bien. Leí que puedes tener equals(TYPE var)oequals(Object o) { (CAST) var } asumir que, dado que funcionaba, no importaba demasiado.
Luego me encontré con un problema: necesitaba crear un Bookobjeto con solo el contenido IDdentro de la clase Libro. No se ingresarán otros datos. Básicamente lo siguiente:
public boolean hasBook(int i) {
Book b = new Book(i);
return hasBook(b);
}
public boolean hasBook(Book b) {
// .. more code here
return this.books.contains(b);
}
De repente, el equals(Book b)método ya no funciona. Esto tomó MUCHO tiempo para rastrear sin un buen depurador y suponiendo que la Cartclase se probó y corrigió correctamente. Después de cambiar el equals()método a lo siguiente:
public boolean equals(Object o) {
Book b = (Book) o;
... // The rest goes here
}
Todo comenzó a funcionar nuevamente. ¿Hay alguna razón por la cual el método decidió no tomar el parámetro Libro a pesar de que claramente era un Bookobjeto? La única diferencia parecía ser que se instanciaba dentro de la misma clase y solo se llenaba con un miembro de datos. Estoy muy muy confundido Por favor, arrojar algo de luz?
fuente

Respuestas:
En Java, el
equals()método que se heredaObjectes:En otras palabras, el parámetro debe ser de tipo
Object. Esto se llama anulación ; su métodopublic boolean equals(Book other)hace lo que se llama sobrecarga alequals()método.Los
ArrayListusos sobrescritosequals()métodos para comparar los contenidos (por ejemplo, para sucontains()yequals()métodos), no sobrecargados queridos. En la mayoría de su código, llamar al que no anuló correctamenteObjectlos iguales estuvo bien, pero no es compatible conArrayList.Por lo tanto, no anular el método correctamente puede causar problemas.
Anulo es igual a lo siguiente cada vez:
El uso de la
@Overrideanotación puede ayudar mucho con errores tontos.Úselo siempre que piense que está anulando el método de una superclase o interfaz. De esa manera, si lo hace de manera incorrecta, obtendrá un error de compilación.
fuente
if (!(other instanceof MyClass))return false;devuelvefalsesiMyClassextiende la otra clase. Pero no volveríafalsesi la otra clase se extendieraMyClass. ¿No deberíaequalser menos contradictorio?Si usa eclipse solo vaya al menú superior
fuente
Ligeramente fuera de tema a su pregunta, pero probablemente vale la pena mencionar de todos modos:
Commons Lang tiene algunos métodos excelentes que puedes usar para anular equals y hashcode. Consulte EqualsBuilder.reflectionEquals (...) y HashCodeBuilder.reflectionHashCode (...) . Me ahorró mucho dolor de cabeza en el pasado, aunque, por supuesto, si solo quiere hacer "iguales" en la identificación, puede que no se ajuste a sus circunstancias.
También estoy de acuerdo en que debe usar la
@Overrideanotación siempre que anule iguales (o cualquier otro método).fuente
right click -> source -> generate hashCode() and equals(),Otra solución rápida que ahorra código repetitivo es la anotación Lombok EqualsAndHashCode . Es fácil, elegante y personalizable. Y no depende del IDE . Por ejemplo;
Vea las opciones disponibles para personalizar qué campos usar en los iguales. Lombok está disponible en maven . Simplemente agréguelo con el alcance proporcionado :
fuente
en Android Studio es alt + insert ---> equals y hashCode
Ejemplo:
fuente
Considerar:
fuente
objse declara como unObject. El punto de herencia es que luego puede asignar unBookaobj. Después de eso, a menos que sugiera que unObjectno debería ser comparable a unaStringvíaequals(), este código debería ser perfectamente legal y de devoluciónfalse.la
instanceOfdeclaración se usa a menudo en la implementación de iguales.¡Esta es una trampa popular!
El problema es que el uso
instanceOfviola la regla de simetría:(object1.equals(object2) == true)si y solo si(object2.equals(object1))si el primer igual es verdadero y object2 es una instancia de una subclase de la clase a la que pertenece obj1, ¡el segundo igual devolverá falso!
si la clase considerada a la que pertenece ob1 se declara como final, entonces este problema no puede surgir, pero en general, debe probar lo siguiente:
this.getClass() != otherObject.getClass();si no, devuelve falso, de lo contrario, pruebe los campos para comparar la igualdad.fuente
equals()método. Recomienda contra el usogetClass(). La razón principal es que hacerlo rompe el Principio de sustitución de Liskov para las subclases que no afectan la igualdad.recordId es propiedad del objeto
fuente