Alternate names: SuperEqualsIsObjectEquals
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:
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:
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:
// 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);
}
Suppress false positives by adding the suppression annotation @SuppressWarnings("SuperCallToObjectMethod")
to the enclosing element.