重写父类equals()方法时,是否需重写hashcode()方法以遵守二者契约?
hashCode() when overriding equals()? Short answer: Yes, absolutely—you can't skip overriding hashCode() if you've overridden equals(). This is required to uphold the contract defined in Java's Object class, which is critical for your objects to work correctly with hash-based collections (like HashMap, HashSet, LinkedHashMap) and any other logic that relies on hash codes.
The Core Contract Rules
Let's break down the non-negotiable rules between equals() and hashCode():
- If two objects are equal (i.e.,
a.equals(b)returnstrue), then theirhashCode()methods must return the same integer value. - The reverse isn't required: two objects can have the same hash code without being equal (this is called a hash collision, and it's normal—collections handle this by checking
equals()after grouping by hash code).
What Happens If You Ignore This?
Imagine you have a simple User class where you override equals() to compare id fields, but leave hashCode() as the default implementation from Object:
public class User { private String id; private String name; // Constructor, getters, setters... @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return Objects.equals(id, user.id); } // NO hashCode() override here! }
Now try using this in a HashMap:
User user1 = new User("123", "Alice"); User user2 = new User("123", "Bob"); HashMap<User, String> map = new HashMap<>(); map.put(user1, "Alice's data"); // This will return null, even though user1.equals(user2) is true! System.out.println(map.get(user2));
Why? The default hashCode() uses the object's memory address. Even though user1 and user2 are equal, they have different hash codes, so the HashMap looks in different buckets and never finds the entry for user1.
How to Fix It
Always override hashCode() alongside equals(), using the same fields that you used in your equals() logic. For the User example, that's just the id field:
@Override public int hashCode() { return Objects.hash(id); }
If your equals() uses multiple fields (say id and email), include all of them in hashCode():
@Override public int hashCode() { return Objects.hash(id, email); }
Using Objects.hash() is the cleanest way—it handles null values automatically and generates a reasonable hash code.
Key Takeaway
Skipping hashCode() when you override equals() breaks the contract and leads to unpredictable behavior in hash-based collections. It's not a "best practice"—it's a requirement to ensure your objects behave as expected.
内容的提问来源于stack exchange,提问作者luczi94

