Object Equality Use Equals
ID |
java.object_equality_use_equals |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Java |
Tags |
CWE:480, reliability, suspicious-comparison |
Description
Reports uses of == or != to compare two objects of a type that defines its own equals(). The identity operators test whether two references point to the same object in memory, not whether they are logically equal, leading to subtle bugs.
Rationale
The == operator checks reference identity, not logical equality. Two distinct objects that represent the same value will compare as not equal:
Money a = new Money(1000);
Money b = new Money(1000);
if (a == b) { // false: different objects, although Money.equals says they are equal
process();
}
This mistake is common when working with value objects, DTOs and entities.
Scope
The rule reports only when both operands resolve to a type declared in the analyzed project that defines its own equals(). Anything it cannot establish stays unreported, because an unresolved type is not evidence of a defect. In particular the following are never flagged:
-
nullchecks (a == null,a != null) -
thison either side, which covers theif (this == o) return true;short-circuit at the head of anequals()implementation -
enum comparisons (
status == Status.ACTIVE) —==is the recommended idiom for enums -
Classobjects (type == String.class), which are canonical -
primitives, boxed primitives and
Object-typed operands -
Stringcomparisons — handled by the companion rulejava.string_equality_use_equals -
a class that does not define
equals()at all, where identity is the only comparison available and therefore the intended one -
any type declared outside the analyzed project. The project-wide software model does not index the JDK or third-party libraries, so for an imported type the rule can establish neither enum-ness nor an
equals()override, and stays silent