Equality by value asks whether two objects are logically interchangeable, rather than whether two references designate the same object. In Java, == compares references; equals() is the conventional operation for logical equality. Every object is equal to itself, but a well-defined equals() may also treat distinct instances as equal. section 7.1
Integer i1 = 100; Integer i2 = 100; System.out.println(i1 == i2); #1
Autoboxing can make reference equality appear to work: two Integer references for a cached small value may designate the same object. That coincidence is not a value-comparison rule. section 7.1
Do not assume equals() always compares contents. Its inherited Object implementation is identity-based, so separate arrays, StringBuilder instances, atomic variables, references, and some keys can remain unequal despite similar payloads. Select the comparison API that matches the type: Arrays.equals() or Arrays.deepEquals() for arrays, compareTo() for StringBuilder content, and get() when comparing atomic payloads after updates have finished. section 7.2 section 7.15
Use value equality defensively:
- Compare primitive wrappers with equals(), not ==; caching can conceal the error until values or construction paths change. section 7.1
- Check that the argument has the intended type. equals(Object) accepts unrelated objects and normally returns false without a compiler error. section 7.5
- When defining equality, compare the corresponding fields, include every semantically relevant field, and prefer IDE generation or records where suitable. section 7.6 section 7.15
- Keep hashCode() consistent with equals(). Equal objects must yield compatible hashes, especially when equality uses unordered or case-insensitive rules. section 7.8
- Avoid mutating objects after using them as HashMap keys or HashSet elements; changed equality or hashing state can make entries unreachable. section 8.6
A correct call can still be the wrong comparison
"anonymous".equals(name) safely handles a null String value, but it silently returns false if name was accidentally changed from String to String[]. Because equals accepts Object, a refactoring from a single value to a collection or array can preserve compilation while disabling a condition. Treat unexpected false results as possible type mismatches, not only unequal values. section 7.5
Equality is consequential because collections and algorithms use it implicitly. A malformed implementation may quietly lose entries, deduplicate distinct objects, or make HashMap and HashSet lookups fail. Tests should include pairs that differ in each individual equality field and cases exercising the matching hashCode() behavior. section 7.0 section 7.6 section 7.8


