The Object Class: Root of Every Type

Introduction

Every class in Java extends java.lang.Object directly or indirectly. Object provides methods all instances inherit: toString, equals, hashCode, getClass, and more. Overriding these correctly is essential for logging, collections, and domain logic.

Prerequisites

Implicit Inheritance

java
public class Book {
    private String title;
}

Compiler treats this as:

java
public class Book extends Object {

1) toString()

Default prints class name and hash—rarely useful in logs.

java
@Override
public String toString() {
    return "Book{title='" + title + "'}";
}
java
System.out.println(book);  // println calls toString()

2) equals() — Content Equality

== compares references. equals() compares logical equality when overridden.

java
@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Book book = (Book) obj;
    return Objects.equals(title, book.title);
}

Use java.util.Objects.equals and Objects.hash to handle null safely.

For records, equals/hashCode/toString are generated automatically.

3) hashCode() — Hash Buckets

HashMap and HashSet use hashCode() to locate buckets. Contract: if a.equals(b), then a.hashCode() == b.hashCode().

java
@Override
public int hashCode() {
    return Objects.hash(title);
}

Override equals and hashCode together—breaking the contract breaks sets and maps.

4) getClass()

Returns runtime Class<?> metadata (reflection basics). Different from getClass() == other.getClass() type checks in equals.

5) Other Methods (Awareness)

MethodPurpose
clone()shallow copy—use carefully
finalize()deprecated cleanup hook
wait / notifythreading (Multithreading)

Example: Complete Book Equality

java
import java.util.Objects;
 
public class Book {
    private final String isbn;
    private String title;
 
    public Book(String isbn, String title) {
        this.isbn = isbn;
        this.title = title;
    }
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Objects.equals(isbn, book.isbn);
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(isbn);
    }
 
    @Override
    public String toString() {
        return "Book{isbn='" + isbn + "', title='" + title + "'}";
    }
}

Business key isbn defines equality; title may change without changing identity.

Common Beginner Mistakes

Overriding equals Without hashCode

Sets/maps behave incorrectly—duplicates or lost entries.

Using == for String Content

Use .equals() for String characters.

Symmetric equals Broken

Check null and type before casting.

What’s Next

Organize types in Packages, then contracts with Interfaces.

FAQ

Do I override Object methods in every class?

Override when objects go into collections or when readable toString helps debugging.

Can I use IDE generators?

Yes—IntelliJ can generate equals/hashCode/toString safely.

How do records relate to Object?

Records extend Object and auto-generate equals, hashCode, toString from components.

What about equals with inheritance?

Prefer getClass() check for exact type, or instanceof pattern in newer Java for subclasses—advanced equality design.

Is hashCode cryptographic hash?

No. It is a fast bucket index, not security.