An equality contract defines how an `equals()` implementation must behave: an object compares consistently with itself and peers, handles `null`, and preserves symmetric and transitive results. Its paired `hashCode()` rule is essential: objects equal under `equals()` must return the same hash code. section 7.6 section 7.7
Malformed equality code can silently compare the wrong fields, dereference nullable fields, or make a value unequal to itself. A particularly easy typo is comparing one field with itself rather than with the corresponding field on the other object. Prefer generated `equals()` and `hashCode()`, use `Objects.equals()` for nullable fields, and regenerate both methods when participating fields change. section 7.6
Equal arrays, different hash buckets
Content-based `equals()` for array fields must be matched by content-based hashing. `Objects.hash(intData, stringData)` delegates to array `hashCode()`, which does not use array contents; two equal `DataHolder` values can therefore both remain in a `HashSet`. Hash the arrays with `Arrays.hashCode()` instead. section 7.7
The listing creates two array-backed values that compare equal, then shows how an incompatible hash code prevents `HashSet` deduplication. section 7.7
Tests must check the contract directly rather than assume `assertNotEquals()` proves inequality. When equality is asymmetric or one argument is `null`, TestNG 7.4.0 `assertNotEquals()` can succeed without exposing the faulty direction. A dedicated verifier can test many contract conditions that are difficult to enumerate manually. section 10.6 section 7.6
