This article describes a technique for rewriting (override) the Equals method. Using this technique, you can still meet the conventions of the Equals method even when the subclass of the entity class adds a new field (field).
In the 8th of the book Effective Java, Josh Bloch The difficulty of meeting the equals contract when subclasses are described as: the most fundamental problem of equivalence in object-oriented languages. Bloch wrote:
There is no way that you can extend a non-instance class and add a value component while still satisfying the equals convention. Unless you are willing to give up the advantage of object-oriented abstraction.
The 28th chapter in the book Programming in Scala provides a method by which subclasses can extend to non-instance classes and add value components while satisfying equals conventions. While the technique provided in the book is used to define Scala classes, it applies to class definitions in Java as well. In this article, in order to explain this approach, I'll use the relevant chapters in "Programming in Scala", adapt the relevant text, and convert the Scala sample code in the original book to Java code.
The common equivalent trap
Class Java.lang.Object defines a Equals method in which subclasses can be rewritten (override). Unfortunately, the final results show that it is difficult to write the correct equivalence method in object-oriented languages. In fact, after studying a large number of text in Java code, several authors concluded in a 2007 paper that almost all of the equals methods were implemented incorrectly.
This is a serious problem because the equivalence method is fundamental to a lot of code. First, for Type C, an incorrect equivalence method may mean that you cannot reliably put an object of type C into the collection. You may have two equivalent types C element elem1, elem2, that is, "em1.equals (ELEM2)" Output true. However, in the following example, the implementation of the Equals method is a common error:
Set< C> hashSet = new java.util.HashSet< C>();
hashSet.add(elem1);
hashSet.contains(elem2); // 返回 false!
There are four common pitfalls that can cause inconsistent behavior when you overwrite equals:
Use the wrong stereotype to define equals.
Change equals without changing hashcode at the same time.
Variable fields (field) are involved when defining equals.
The equals definition could not be successfully defined as an equivalence relation.
These four traps will be specifically described in the following article.
Trap 1: Define equals with the wrong stereotype
In the following code, we add an equivalence method for the class of ordinary points:
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
// ...
}