93 lines
2.4 KiB
Plaintext
93 lines
2.4 KiB
Plaintext
This rule raises an issue when a subclass of a class that overrides `Object.equals` introduces new fields
|
|
but does not also override the `Object.equals` method.
|
|
|
|
== Why is this an issue?
|
|
|
|
When a class overrides `Object.equals`, this indicates that the class not just considers object identity as equal
|
|
(the default implementation of `Object.equals`) but implements another logic for what is considered equal in the context of this class.
|
|
Usually (but not necessarily), the semantics of `equals` in this case is that two objects are equal when their state is equal field by field.
|
|
|
|
Because of this, adding new fields to a subclass of a class that overrides `Object.equals` but not updating the implementation of `equals`
|
|
in the subclass is most likely an error.
|
|
|
|
== How to fix it
|
|
|
|
Consider the following example:
|
|
|
|
[source,java]
|
|
----
|
|
|
|
class Foo {
|
|
|
|
final int a;
|
|
|
|
@Override
|
|
public boolean equals(Object other) {
|
|
if (other == null) return false;
|
|
if (getClass() != other.getClass()) return false;
|
|
return a == ((Foo) other).a;
|
|
}
|
|
}
|
|
----
|
|
|
|
[source,java,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
class Bar extends Foo { // Noncompliant, `equals` ignores the value of `b`
|
|
final int b;
|
|
}
|
|
----
|
|
|
|
Override the `equals` method in the subclass to incorporate the new fields into the comparison:
|
|
|
|
[source,java,diff-id=1,diff-type=compliant]
|
|
----
|
|
class Bar extends Foo { // Compliant, `equals` now also considers `b`
|
|
|
|
final int b;
|
|
|
|
@Override
|
|
public boolean equals(Object other) {
|
|
if (!super.equals(other)) return false;
|
|
return b == ((Bar) other).b;
|
|
}
|
|
}
|
|
----
|
|
|
|
In case the new fields should not be part of the comparison because they are, for example,
|
|
auxiliary variables not contributing to the object value (), still override the method to make the point clear
|
|
that this was not just forgotten:
|
|
|
|
[source,java,diff-id=1,diff-type=compliant]
|
|
----
|
|
class Bar extends Foo { // Compliant, we do explicitly not want to take `b` into account
|
|
|
|
final int b;
|
|
|
|
@Override
|
|
public boolean equals(Object other) {
|
|
return super.equals(other);
|
|
}
|
|
}
|
|
----
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-[Object.equals - Java SE 8 API Specification]
|
|
|
|
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
Override the "equals" method in this class
|
|
|
|
|
|
endif::env-github,rspecator-view[]
|