JavaThe Object Class

The Object Class

Every class in Java implicitly extends Object if it doesn't explicitly extend anything else. As covered on the Inheritance page, extends normally lets you choose a parent — but if you leave it out entirely, Java silently inserts extends Object for you. This means every single object you ever create — every String, every ArrayList, every custom class — inherits a baseline set of methods from Object.

Key inherited methods

Method

Purpose

toString()

Returns a String representation of the object, used by println, string concatenation, and debuggers

equals(Object o)

Determines whether this object is considered equal to another

hashCode()

Returns an integer used to place the object in hash-based collections like HashMap and HashSet

getClass()

Returns the runtime Class object representing this object's actual type

Overriding toString()

Object's default toString() produces the class name followed by @ and a hexadecimal hash code — technically correct, but not remotely useful for debugging.

The default toString()

Java
class Point {
    int x, y;
    Point(int x, int y) { this.x = x; this.y = y; }
}

Point p = new Point(3, 4);
System.out.println(p); // Point@1b6d3586  <- not useful

Overriding toString() to return something meaningful is common practice for almost every class you write, so that logging, printing, and debugging give you real information instead of a hash code.

A useful toString()

Java
class Point {
    int x, y;
    Point(int x, int y) { this.x = x; this.y = y; }

    @Override
    public String toString() {
        return "Point(" + x + ", " + y + ")";
    }
}

Point p = new Point(3, 4);
System.out.println(p); // Point(3, 4)
Point(3, 4)
The equals() / hashCode() contract

Object's default equals() compares references — two objects are “equal” only if they are literally the same object in memory. It's very common to override equals() so that two distinct objects are considered equal when their field values match, exactly the way records do automatically.

Critical rule: override both, or neither
If you override `equals()`, you **must** also override `hashCode()` so that any two objects considered equal by `equals()` always produce the same `hashCode()`. Breaking this contract silently corrupts hash-based collections: a `HashMap` or `HashSet` uses `hashCode()` first to find the right bucket, then `equals()` to confirm a match inside that bucket. If two “equal” objects hash differently, a `HashSet` can end up storing duplicate entries, and `map.get(key)` can fail to find a value that was clearly put in with an “equal” key — one of the most notorious, hard-to-spot bug classes in Java.

Overriding both together

Java
import java.util.Objects;

class Point {
    int x, y;
    Point(int x, int y) { this.x = x; this.y = y; }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Point)) return false;
        Point other = (Point) o;
        return x == other.x && y == other.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y); // consistent with equals() above
    }
}
  • Every class implicitly extends Object unless it extends something else explicitly.

  • toString(), equals(), hashCode(), and getClass() are inherited by every object.

  • Override toString() for meaningful debug output — the default is just a class name and hash code.

  • Always override equals() and hashCode() together — never just one.