Frage

Ich lief in eine interessante (und sehr frustrierende) Problem mit der equals() Methode heute verursacht, was ich dachte, eine gut getestete Klasse zum Absturz zu bringen und verursachen einen Fehler, der brauchte eine sehr lange Zeit auf die Spur.

Nur der Vollständigkeit halber, ich war nicht mit einem IDE-oder debugger - just good old fashioned text-editor und System.aus ist.Die Zeit war sehr begrenzt, und es war ein Schulprojekt.

Wie auch immer -

Ich war die Entwicklung eines basic Einkaufswagen, die könnte enthalten ein ArrayList von Book Objekte.Um die Durchführung der addBook(), removeBook(), und hasBook() Methoden der Wagen, ich wollte überprüfen, ob die Book bereits in der Cart.Also gehe ich aus -

public boolean equals(Book b) {
    ... // More code here - null checks
    if (b.getID() == this.getID()) return true;
    else return false;
}

Alles funktioniert gut, im Test.I create 6 Objekte und füllen Sie diese mit Daten.Viele Hinzugefügt, entfernt hat () - Operationen auf Cart und alles funktioniert gut.Ich habe gelesen, dass Sie können entweder haben equals(TYPE var) oder equals(Object o) { (CAST) var } aber angenommen, dass, da es arbeitete, spielte es keine Rolle, zu viel.

Dann lief ich in ein problem - ich benötigt wird, um eine Book Objekt mit nur die ID in es aus der Book-Klasse.Keine weiteren Daten in Sie eingegeben.Grundsätzlich sind die folgenden:

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);
}

Alle von einer plötzlichen, die equals(Book b) Methode nicht mehr funktioniert.Dies dauerte eine SEHR lange Zeit auf die Spur, ohne einen guten debugger und vorausgesetzt, die Cart Klasse wurde ordnungsgemäß getestet und korrigieren.Nach swaapping der equals() Methode, die der folgenden:

public boolean equals(Object o) {
    Book b = (Book) o;
    ... // The rest goes here   
}

Alles begann wieder zu arbeiten.Gibt es einen Grund, die Methode, die beschlossen, nicht zu nehmen das Buch-parameter, obwohl es eindeutig war ein Book Objekt?Der einzige Unterschied schien zu sein, es instanziiert wurde in der gleichen Klasse, und nur gefüllt mit einer Daten-Mitglied.Ich bin sehr, sehr verwirrt.Bitte, etwas Licht?

War es hilfreich?

Lösung

In Java, die equals() Methode geerbt von Object ist:

public boolean equals(Object other);

In anderen Worten, der parameter muss vom Typ Object.

Die ArrayList verwendet der richtigen equals-Methode, wo Sie waren, ruft immer die, die nicht richtig überschreiben Object's gleich.

Nicht zu überschreiben die Methode richtig Probleme verursachen können.

Ich überschreiben entspricht den folgenden everytime:

@Override
public boolean equals(Object other){
    if (other == null) return false;
    if (other == this) return true;
    if (!(other instanceof MyClass))return false;
    MyClass otherMyClass = (MyClass)other;
    ...test other properties here...
}

Die Verwendung des @Override annotation kann helfen, eine Tonne mit dummen Fehlern.

Verwenden Sie es, Wann immer Sie denken, dass Sie ein überwiegendes super-Klasse " oder interface-Methode.So, wenn Sie es falsch machen, erhalten Sie einen Kompilierungsfehler.

Andere Tipps

Wenn Sie Eclipse nur nach oben Menü gehen Sie mit

  

Quelle -> Gene equals () und   hashCode ()

Ein wenig vom Thema auf Ihre Frage, aber es ist wahrscheinlich erwähnenswert, trotzdem:

Commons Lang hat einige ausgezeichnete Methoden bekam man in zwingende equals und hashcode verwenden können. Check out EqualsBuilder.reflectionEquals (...) und HashCodeBuilder.reflectionHashCode (... ). Ersparte mir viele Kopfschmerzen in der Vergangenheit -. Obwohl natürlich, wenn Sie gerade tun wollen „gleich“ auf ID nicht Ihre persönlichen Umstände passen

Ich bin damit einverstanden, dass Sie die @Override Anmerkung verwenden sollen, wenn Sie überschreiben equals (oder eine andere Methode).

Eine weitere schnelle Lösung, die vorformulierten Code speichert Lombok EqualsAndHashCode Anmerkung . Es ist einfach, elegant und anpassbar. Und ist, hängt nicht von der IDE . Zum Beispiel:

import lombok.EqualsAndHashCode;

@EqualsAndHashCode(of={"errorNumber","messageCode"}) // Will only use this fields to generate equals.
public class ErrorMessage{

    private long        errorNumber;
    private int         numberOfParameters;
    private Level       loggingLevel;
    private String      messageCode;

Sehen Sie die Optionen avaliable anpassen, die in den Gleichen verwenden Felder. Lombok ist avalaible in Maven . Fügen Sie es einfach mit zur Verfügung gestellt Anwendungsbereich:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.14.8</version>
    <scope>provided</scope>
</dependency>

in Android Studio alt + einfügen ---> gleich und hashCode

Beispiel:

    @Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Proveedor proveedor = (Proveedor) o;

    return getId() == proveedor.getId();

}

@Override
public int hashCode() {
    return getId();
}

Bedenken Sie:

Object obj = new Book();
obj.equals("hi");
// Oh noes! What happens now? Can't call it with a String that isn't a Book...

die instanceOf Aussage oft bei der Umsetzung von Gleichen verwendet wird.

Dies ist eine beliebte pitfall!

Das Problem ist, dass die Verwendung von instanceOf die Regel Symmetrie verletzt:

(object1.equals(object2) == true) , wenn und nur wenn (object2.equals(object1))

, wenn die erste gleich wahr ist, und object2 ist eine Instanz einer Unterklasse von die Klasse, in der obj1 gehört, dann die zweite equals wird return false

, wenn die betrachtete Klasse, wo ob1 gehört als final deklariert, dann ist diese Problem kann nicht auftreten, aber im Allgemeinen, sollten Sie testen, wie folgt:

this.getClass() != otherObject.getClass(); wenn nicht, return false, sonst Test die Felder für die Gleichstellung vergleichen!

recordID ist Eigenschaft des Objekts

@Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Nai_record other = (Nai_record) obj;
        if (recordId == null) {
            if (other.recordId != null)
                return false;
        } else if (!recordId.equals(other.recordId))
            return false;
        return true;
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top