Reference types that declare an
equals() method, or that inherit
from a type other than
Object, should not be compared for reference equality
!=. Instead, always compare for value equality with
It’s dangerous to rely on your instances being interned. We have no tooling to check or enforce that, and it’s easy to get wrong.
Booleanvalues? We know there’s just
null). Surely they’re okay!
Well, no, because some tricky client can always generate a new instance with
new Boolean(true). Comparing with
equals always works; comparing with
enumvalues are always unique, so can’t I compare them with
Yes, but that might confuse the reader, who must understand that your type has
special properties because it’s an
equals everywhere can work
the same everywhere; special-casing for enums isn’t worth it.
We do exempt methods that override
Object#equals() from this check. In other
Type#equals() should be just as fast, because that method will
likely be inlined, and the first thing it will likely do is that same instance
Alternatively, if you’re okay with accepting null, you could call
java.util.Objects.equals(), which first does a reference equality comparison
and then falls back to content equality for non-null arguments.
Both Truth and JUnit provide clearer ways to assert this.
assertSame(b, a); assertNotSame(b, a);
equals to express when two instances should be treated as
interchangeable with each other. Predominant Java libraries and practices are
built on that assumption. Defining a “magic instance” for such a type goes
against this whole practice, leaving you vulnerable to unexpected bugs.
Consider choosing a sentinel value within the domain of the type (the moral
-1 for indexOf function calls) that you could compare against
using the normal
Optional<V> as the value type of your map instead.
Suppress false positives by adding the suppression annotation
@SuppressWarnings("ReferenceEquality") to the enclosing element.