Object Class Root: equals(), hashCode() & toString() Contract
1Concept
`java.lang.Object` is the root of the entire Java class hierarchy. The equals/hashCode contract dictates: If two objects are equal according to `equals()`, they MUST produce the exact same `hashCode()`. Failing this contract corrupts HashMaps and HashSets.
2Architecture Diagram
Object Contract: objA.equals(objB) == true =====> objA.hashCode() MUST EQUAL objB.hashCode() objA.hashCode() == objB.hashCode() =====> objA may or may not equal objB (Hash Collision)
3Code Example
Core Java
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
public class ObjectContractDemo {
static class Employee {
int id;
String name;
Employee(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee e)) return false;
return id == e.id && Objects.equals(name, e.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "Employee[id=" + id + ", name=" + name + "]";
}
}
public static void main(String[] args) {
Set<Employee> team = new HashSet<>();
Employee e1 = new Employee(101, "Alice");
Employee e2 = new Employee(101, "Alice");
team.add(e1);
team.add(e2);
System.out.println("HashSet Size: " + team.size() + " (Deduplicated correctly!)");
System.out.println("Employee representation: " + e1);
}
}4Expected Output
HashSet Size: 1 (Deduplicated correctly!) Employee representation: Employee[id=101, name=Alice]
5Key Takeaways
- ✓Always override `hashCode()` whenever you override `equals()`.
- ✓Use `java.util.Objects.hash()` and `Objects.equals()` for clean null-safe implementations.
- ✓Never use non-deterministic fields (like timestamps) in equals/hashCode.