Object Class: equals, hashCode, toString
Every class implicitly extends the Object class, so every object gets toString(), equals(), and hashCode() for free.
The default toString() gives odd-looking text (like ClassName@hashcode) — which is why we override it for readable output.
equals() and hashCode() should be overridden together — this is essential for HashMap/HashSet to work correctly.
class Point {
int x, y;
public String toString() { return "(" + x + "," + y + ")"; }
public boolean equals(Object o) {
if (!(o instanceof Point)) return false;
Point p = (Point) o;
return x == p.x && y == p.y;
}
}- Every object gets these from the Object class
- Override toString() for readable text
- Override equals()+hashCode() together
equals() must follow a formal contract: reflexive (a.equals(a) is always true), symmetric (a.equals(b) == b.equals(a)), transitive (if a=b and b=c then a=c), and consistent (calling it repeatedly without changing data gives the same result). Breaking these rules causes weird, hard-to-debug bugs in Collections (HashMap, HashSet).
Rule: if two objects are equal by equals(), their hashCode() *must* also match (the reverse isn't required — different objects can share the same hashCode, called a "collision", and HashMap handles that fine). This is why, whenever you override equals(), always override hashCode() alongside it — otherwise duplicate detection in HashMap/HashSet breaks, and the same "equal" object could get added twice!
class Point {
int x, y;
public boolean equals(Object o) { /* x,y compare */ return true; }
public int hashCode() { return Objects.hash(x, y); } // dono saath
}The default toString() (ClassName@hashcode, like Point@1b6d3586) is useless for debugging. Override it to give a meaningful representation — like "Point{x=3, y=5}". IDEs and logging tools automatically use toString() whenever an object is printed or viewed in a debugger.
Calling .getClass() on any object gives you its runtime class (obj.getClass().getName()) — this is sometimes used in an equals() implementation instead of instanceof (for strict type matching). This is the entry point to the "Reflection" API — an advanced feature that lets you inspect/call classes/methods at runtime (frameworks like Spring depend heavily on this, for dependency injection).