Heim >Java >javaLernprogramm >Überschreiben der Methode equal()

Überschreiben der Methode equal()

高洛峰
高洛峰Original
2016-12-16 10:38:071416Durchsuche

1. Warum muss die Methode equal() neu geschrieben werden?

Bestimmen Sie, ob zwei Objekte logisch gleich sind, indem Sie beispielsweise anhand der Mitgliedsvariablen der Klasse beurteilen, ob Instanzen zweier Klassen gleich sind. Die Methode „equals“ im geerbten Objekt kann jedoch nur bestimmen, ob zwei Referenzvariablen gleich sind dasselbe. Auf diese Weise müssen wir häufig die Methode equal() überschreiben.

Wenn wir Elemente zu einer Sammlung ohne doppelte Objekte hinzufügen, speichert die Sammlung häufig Objekte. Wir müssen zunächst feststellen, ob es bekannte Objekte in der Sammlung gibt, daher müssen wir die Methode „equals“ überschreiben.

2. Wie überschreibe ich die Methode equal()?

Anforderungen zum Überschreiben der Methode „equals“:
1. Reflexivität: x.equals(x) sollte für jede Nicht-Null-Referenz x „true“ zurückgeben.
2. Symmetrie: Wenn x.equals(y) für jede Referenz auf x und y true zurückgibt, sollte y.equals(x) auch true zurückgeben.
3. Transitivität: Wenn für jede Referenz x, y und z x.equals(y) true und y.equals(z) true zurückgibt, sollte x.equals(z) auch true zurückgeben.
4. Konsistenz: Wenn sich die durch x und y referenzierten Objekte nicht geändert haben, sollte der wiederholte Aufruf von x.equals(y) das gleiche Ergebnis zurückgeben.
5. Nicht-Nullbarkeit: Für jede Nicht-Null-Referenz x sollte x.equals(null) false zurückgeben.

Format:


Java-Code

public boolean equals(Object obj) {  
    if(this == obj)  
        return false;  
    if(obj == null)  
        return false;  
    if(getClass() != obj.getClass() )  
        return false;  
    MyClass other = (MyClass)obj;  
    if(str1 == null) {  
         if(obj.str1 != null) {  
              return false;  
         }  
    }else if (!str1.equals(other.str1) )  
             return false;  
     }  
    if(var1 != other.var1)  
        return false;  
    return true;  
}

Wenn der Unterklasse neue Funktionen hinzugefügt werden und dabei die Methode „equals“ beibehalten wird, dann ist dies der Fall komplizierter.


Als nächstes wollen wir die obige Konvention anhand von Beispielen verstehen. Wir beginnen mit einer einfachen, nicht veränderlichen 2D-Punktklasse:

public class Point{ 
  private final int x; 
  private final int y; 
  public Point(int x, int y){ 
    this.x = x; 
    this.y = y; 
  } 
  public boolean equals(Object o){ 
    if(!(o instanceof Point)) 
      return false; 
    Point p = (Point)o; 
      return p.x == x && p.y == y; 
  } 
}


Angenommen, Sie möchten diese Klasse erweitern, um einem Punkt Farbinformationen hinzuzufügen:

public class ColorPoint extends Point{ 
  private Color color; 
  public ColorPoint(int x, int y, Color color){ 
    super(x, y); 
    this.color = color; 
  } 
  //override equasl() 
  public boolean equals(Object o){ 
    if(!(o instanceof ColorPoint)) 
     return false; 
    ColorPoint cp = (ColorPoint)o; 
    return super.equals(o) && cp.color==color; 
  } 
}


Wir überschreiben die Methode „equals“, sodass sie nur dann „true“ zurückgibt, wenn der tatsächliche Parameter ein anderer farbiger Punkt mit derselben Position und Farbe ist. Das Problem bei dieser Methode besteht jedoch darin, dass Sie beim Vergleich eines normalen Punkts mit einem farbigen Punkt und umgekehrt möglicherweise unterschiedliche Ergebnisse erhalten:

public static void main(String[] args){ 
  Point p = new Point(1, 2); 
  ColorPoint cp = new ColorPoint(1, 2, Color.RED); 
  System.out.println(p.equals(cp)); 
  System.out.println(cp.eqauls(p)); 
}

Laufergebnisse:
wahr
false
Ein solches Ergebnis verstößt offensichtlich gegen die Symmetrie. Sie können Folgendes versuchen, um dieses Problem zu beheben: Lassen Sie ColorPoint.equals Farbinformationen ignorieren, wenn Sie „gemischte Vergleiche“ durchführen:

public boolean equals(Object o){ 
  if(!(o instanceof Point)) 
    return false; 
  //如果o是一个普通点,就忽略颜色信息 
  if(!(o instanceof ColorPoint)) 
    return o.equals(this); 
  //如果o是一个有色点,就做完整的比较 
  ColorPoint cp = (ColorPoint)o; 
  return super.equals(o) && cp.color==color; 
}

Was wird sein das Ergebnis dieser Methode? Testen wir es zuerst:

public static void main(String[] args){ 
  ColorPoint p1 = new ColorPoint(1, 2, Color.RED); 
  Point p2 = new Point(1, 2); 
  ColorPoint p3 = new ColorPoint(1, 2, Color.BLUE); 
  System.out.println(p1.equals(p2)); 
  System.out.println(p2.equals(p1)); 
  System.out.println(p2.equals(p3)); 
  System.out.println(p1.eqauls(p3)); 
}

Laufendes Ergebnis:
wahr
wahr
wahr
falsch

Diese Methode bietet zwar Symmetrie, aber bei der Aufwand der Transitivität (konventionell geben sowohl p1.equals(p2) als auch p2.eqauals(p3) true zurück, und p1.equals(p3) sollte auch true zurückgeben). Wie kann man es lösen?

Tatsächlich ist dies eine grundlegende Frage zu Äquivalenzbeziehungen in objektorientierten Sprachen. Es gibt keine einfache Möglichkeit, eine instanziierbare Klasse zu erweitern, um neue Funktionen hinzuzufügen und dabei die Gleichheitskonvention beizubehalten. Die neue Lösung besteht darin, ColorPoint nicht mehr Point erweitern zu lassen, sondern ein privates Point-Feld und eine öffentliche Ansichtsmethode zu ColorPoint hinzuzufügen:

public class ColorPoint{ 
  private Point point; 
  private Color color; 
  public ColorPoint(int x, int y, Color color){ 
    point = new Point(x, y); 
    this.color = color; 
  } 
  //返回一个与该有色点在同一位置上的普通Point对象 
  public Point asPoint(){ 
    return point; 
  } 
  public boolean equals(Object o){ 
    if(o == this) 
     return true; 
    if(!(o instanceof ColorPoint)) 
     return false; 
    ColorPoint cp = (ColorPoint)o; 
    return cp.point.equals(point)&& 
             cp.color.equals(color); 
  } 
}

Es gibt noch eine andere Die Lösung besteht darin, Point als zu entwerfen eine abstrakte Klasse, sodass Sie Unterklassen der abstrakten Klasse neue Funktionen hinzufügen können, ohne den Equals-Vertrag zu verletzen. Da abstrakte Klassen keine Instanzen der Klasse erstellen können, treten keine der oben genannten Probleme auf.

Wichtige Punkte beim Überschreiben der Methode „equals“:
1. Verwenden Sie den ==-Operator, um zu prüfen, „ob der tatsächliche Parameter eine Referenz auf das Objekt ist“.

2. Bestimmen Sie, ob der tatsächliche Parameter null ist
3. Verwenden Sie den Operator „instanceof“, um zu prüfen, „ob der tatsächliche Parameter vom richtigen Typ ist“.
4. Konvertieren Sie die tatsächlichen Parameter in den richtigen Typ.
5. Überprüfen Sie für jedes „Schlüssel“-Feld in dieser Klasse, ob das Feld im tatsächlichen Parameter mit dem entsprechenden Feldwert im aktuellen Objekt übereinstimmt
. Für Felder mit Basistypen, die weder Float noch Double sind, können Sie zum Vergleich den ==-Operator
verwenden. Für Felder mit Objektreferenztypen können Sie die Methode equal des referenzierten Objekts
rekursiv aufrufen Felder, verwenden Sie zuerst Float.floatToIntBits, um in Werte vom Typ „int“ zu konvertieren,
Verwenden Sie dann den Operator ==, um Werte vom Typ „int“ zu vergleichen Verwenden Sie dann den ==-Operator, um den Wert des Typs
long zu vergleichen.
6. Nachdem Sie die Gleichheitsmethode geschrieben haben, sollten Sie sich drei Fragen stellen: Ist sie symmetrisch, transitiv und konsistent? (Die beiden anderen Merkmale werden normalerweise von selbst erfüllt.) Wenn die Antwort „Nein“ lautet, ermitteln Sie bitte den Grund, warum diese Merkmale nicht erfüllt sind, und ändern Sie dann den Code der Methode „equals“.



Weitere Artikel zum Umschreiben der Methode equal() finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn