(Java) Implementieren von equals () für eine Klasse mit durch Vererbung hinzugefügten Wertelementen

Einführung

Es ist bekannt, dass die Eigenschaften, die equals () erfüllen sollte, nicht durch einfaches Implementieren der equals () -Methode einer Klasse mit einer Vererbungsbeziehung erfüllt werden können, wie unten gezeigt [(Supplement 1)](#Supplement 1). .. [* 1 Referenz](# 1) Die Problemumgehung wird auch in derselben Referenz [(Ergänzung 2)](# Ergänzung 2) beschrieben, aber die Lösung aus einem anderen Dokument [* 2 Referenz](# 2) wird beschrieben. equals_impl.png

Fazit

Erstellen Sie eine statische Methode equals () mit zwei Argumenten, wie unten gezeigt, und rufen Sie Object.equals () auf. Der wichtige Teil ist der Teil, der equals () beider Klassen aufruft. Dies kann außerhalb dieser Klassenstruktur verwendet werden. Volltext Übrigens gibt es Objects.equals (Object, Object) in der Standard-API, aber nur equals () auf der linken Seite wird aufgerufen.

ObjectUtil.java


final class ObjectUtil {
    private ObjectUtil() { throw new AssertionError("Not intended to be instanciated"); }
    public static boolean equals(final Object lhs, final Object rhs) {
        //Gleich, wenn die Referenzziele auf der linken und rechten Seite identisch sind
        if (lhs == rhs) return true;
        //Gleich, wenn sowohl die linke als auch die rechte Referenz null sind
        if (lhs == null && rhs == null) return true;
        //Nicht dasselbe, wenn entweder das Referenzziel auf der linken Seite oder das Referenzziel auf der rechten Seite null ist
        if (lhs == null || rhs == null) return false;
        //Wenn die Referenzziele auf der linken und rechten Seite dieselbe Klasse sind, entspricht dies dieser Klasse()Zurückgeben
        if (lhs.getClass() == rhs.getClass()) return lhs.equals(rhs);
        //Wenn die Referenzen auf der linken und rechten Seite unterschiedliche Klassen sind, sind beide Klassen gleich()Und zurück
        return lhs.equals(rhs) && rhs.equals(lhs);
    }
}

Ergänzung 1

// 1.Die Symmetrie kann nicht erfüllt werden
// ->Wenn Sie die rechte und die linke Seite tauschen, ist das Ergebnis unterschiedlich.
//Beispiel mit der oben gezeigten Klassenstruktur
Point1D p1 = new Point1D(0);
Point2D p2 = new Point2D(0, 0);
assert(p1.equals(p2) == true);  //True, da nur x-Werte verglichen werden
assert(p2.equals(p1) == false); //False, um festzustellen, dass es sich um eine Point2D-Instanz handelt

// 2.Transparenz kann nicht befriedigt werden
// -> p1 == p2 && p2 ==Auch für p3, p1==Wird nicht p3
//Beispiel mit der oben gezeigten Klassenstruktur
//Annahme: Point2D.equals()Fügen Sie den Spezifikationen Folgendes hinzu
//True, auch wenn das Argument Point1D oder seine Unterklasse ist und der x-Wert gleich ist
Point2D p1 = new Point2D(0, 0);
Point1D p2 = new Point1D(0);
Point2D p3 = new Point2D(0, 1);
assert(p1.equals(p2) == true); //Richtig aufgrund neuer Spezifikationen
assert(p2.equals(p3) == true); //true, da x-Werte nicht verglichen werden
assert(p1.equals(p3) == false); // x,false, um y-Werte zu vergleichen

// 3.Das Ersatzprinzip von Riskov kann nicht erfüllt werden
// ->Ein ähnliches Verhalten wird in Unterklassen erwartet, jedoch nicht
//Beispiel mit der oben gezeigten Klassenstruktur
//Annahme 1: Point1D.equals()Ändern Sie die Spezifikationen wie folgt
//Nur wahr, wenn das Argument Point1D ist und der x-Wert gleich ist
//Annahme 2: CountingPoint1D.equals()Ändern Sie die Spezifikationen wie folgt
//Nur wahr, wenn das Argument CountingPoint1D ist und der x-Wert gleich ist
Point1D p1 = new Point(0);
CountingPoint1D cp1 = new CountingPoint(0);
CountingPoint1D cp2 = new CountingPoint(0);
List<CountingPoint1D> list = Arrays.asList(cp1);
assert(list.contains(cp2) == true); // cp1 ==wahr für cp2
assert(list.contains(p1) == false); //Falsch wegen Annahme 1

Ergänzung 2

//Verwenden Sie Komposition anstelle von Vererbung
//Beispiel
class Point2D {
    private final Point1D p1;
    private final int y;
    ...
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Point2D)) return false;
        Point2D rhs = (Point2D)o;
        return p1.equals(rhs.p1) && y.equals(rhs.y);
    }
}

*1 Joshua Brock (2014) "Effective Java 2nd Edition" Maruzen. Punkt 8 *2 Andrey Alexandresque (2013) "Programmiersprache D" Shosuisha. 6.8.3

Recommended Posts

(Java) Implementieren von equals () für eine Klasse mit durch Vererbung hinzugefügten Wertelementen
Zuordnung zu einer Klasse mit einem Wertobjekt in How to My Batis
[Java] Fassen Sie zusammen, wie Sie mit der Methode equals vergleichen können
[Java] So suchen Sie mit der Methode includes nach Werten in einem Array (oder einer Liste)
[Java] So drehen Sie ein zweidimensionales Array mit einer erweiterten for-Anweisung
[Java] [Für Anfänger] So fügen Sie Elemente direkt in ein zweidimensionales Array ein
[Java] So testen Sie, ob es in JUnit null ist
So konvertieren Sie einen Soliditätsvertrag in eine Java-Vertragsklasse
[Java] So erhalten Sie HashMap-Elemente per Schleifensteuerung mithilfe der erweiterten for-Anweisung
[Java] So erhalten Sie eine Anfrage per HTTP-Kommunikation
[Java] So schneiden Sie eine Zeichenfolge zeichenweise aus
[Java] So unterbrechen Sie eine Zeile mit StringBuilder
Verwendung der Java-Klasse
[Java] So implementieren Sie Multithreading
So erstellen Sie ein leichtes Container-Image für Java-Apps
So verschieben Sie eine andere Klasse mit einer Schaltflächenaktion einer anderen Klasse.
Untersucht, wie Dienste mit Watson SDK für Java aufgerufen werden
So erstellen Sie einen Java-Container
So zerlegen Sie eine Java-Klassendatei
So implementieren Sie einen Job, der die Java-API in JobScheduler verwendet
So ändern Sie das Argument in der [Java] -Methode (für diejenigen, die durch Übergabe von Werten, Übergeben von Referenzen, Übergeben von Referenzen verwirrt sind)
So dekompilieren Sie eine Java-Klassendatei
Ersetzen Sie durch einen Wert entsprechend der Übereinstimmung mit einem regulären Java-Ausdruck
Verwendung von Klassenmethoden [Java]
So überprüfen Sie den Inhalt der Java-Zeichenfolge mit fester Länge
So erstellen Sie ein Java-Array
Wie man einen revolutionären Diamanten mit Java für Aussage macht wwww
Wie gehe ich mit dem Typ um, den ich 2 Jahre lang über das Schreiben eines Java-Programms nachgedacht habe?
[Java] Verwendung der Math-Klasse
So implementieren Sie eine Diashow mit Slick in Rails (einzeln und mehrfach nacheinander)
[Persönliches Memo] Interaktion mit dem Zufallszahlengenerator in Java
So finden Sie heraus, welche Java-Version der Klassendatei kompiliert wurde
[Java small story] Überwachen Sie, wann der Liste ein Wert hinzugefügt wird
[Java] Wie man mit der String-Klasse an die Spitze eines bestimmten Strings kommt
Wie ein völlig unerfahrener Mensch studierte, um selbst Java-Silber zu erwerben
Verfolgen, wann sich ein von Scoop verwalteter Bucket ändert (hauptsächlich Java)
So erstellen Sie eine App mit einem Plug-In-Mechanismus [C # und Java]
So erstellen Sie eine Java-Kalenderzusammenfassung
So implementieren Sie die Datumsberechnung in Java
So implementieren Sie den Kalman-Filter mit Java
[Java] Verwendung der File-Klasse
So kompilieren Sie Java mit VsCode & Ant
[Einführung in Java] So schreiben Sie ein Java-Programm
So erstellen Sie ein Maven-Repository für 2020
Wie erstelle ich einen Discord Bot (Java)
So erzwingen Sie Codierungskonventionen in Java
[Verarbeitung × Java] Verwendung der Klasse
So implementieren Sie TextInputLayout mit Validierungsfunktion
Verwendung der Java Scanner-Klasse (Hinweis)
[Java] Verwendung der Calendar-Klasse
Ich habe ein Programm erstellt, das aus dem mit Java überladenen Prozess nach der Zielklasse sucht
So geben Sie ein Glas mit der von gradle in IntellijIDEA angegebenen Hauptklasse aus
So stellen Sie ein mit Java erstelltes System (Wicket-Spring-Boot) auf dem Campus-Server bereit
So testen Sie eine Klasse, die application.properties mit SpringBoot verarbeitet (Anfrage: darauf hingewiesen)