| Implementations of `equals` and `hashCode` should usually not delegate to |
| `Object.equals` and `Object.hashCode`. |
| |
| Those two methods implement equality based on object identity. That |
| implementation *is* sometimes what the author intended. (This check attempts to |
| identify those cases and *not* report a warning for them. But in some cases, it |
| still produces a warning when it shouldn't.) |
| |
| But when `super.equals` and `super.hashCode` call the methods defined in |
| `Object`, the developer often did *not* intend to use object identity. Often, |
| developers write something like: |
| |
| ```java |
| private final int id; |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (obj instanceof Foo) { |
| return super.equals(obj) && id == ((Foo) obj).id; |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return super.hashCode() ^ id; |
| } |
| ``` |
| |
| This appears to be an attempt to define equality in terms of the `id` field in |
| this class and any fields in the superclass. However, when the superclass that |
| defines `equals` or `hashCode` is `Object`, the code instead defines equality in |
| terms of a mix of object identity and field values. The result is equivalent to |
| defining it in terms of identity alone—which is equivalent to not overriding |
| `equals` and `hashCode` at all! |
| |
| Typically, the code should be rewritten to remove the `super` calls entirely: |
| |
| ```java |
| private final int id; |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (obj instanceof Foo) { |
| return id == ((Foo) obj).id; |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return id; |
| } |
| ``` |
| |
| Note that the suggested edits for this check instead preserve behavior, which |
| likely means preserving bugs! However, in cases in which object identity *is* |
| intended, we recommend applying the suggested edit to make that behavior |
| explicit in the code: |
| |
| ```java |
| // This class's definition of equality is unusual and perhaps not ideal. |
| // But it is at least explicit. |
| |
| private final Integer id; |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (obj instanceof Foo) { |
| if (id == null) { |
| return this == obj; |
| } |
| return id.equals(((Foo) obj).id); |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return id != null ? id : System.identityHashCode(this); |
| } |
| ``` |