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
- Inheritance and method overriding
- Strings
Implicit Inheritance
public class Book {
private String title;
}Compiler treats this as:
public class Book extends Object {1) toString()
Default prints class name and hash—rarely useful in logs.
@Override
public String toString() {
return "Book{title='" + title + "'}";
}System.out.println(book); // println calls toString()2) equals() — Content Equality
== compares references. equals() compares logical equality when overridden.
@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().
@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)
| Method | Purpose |
|---|---|
clone() | shallow copy—use carefully |
finalize() | deprecated cleanup hook |
wait / notify | threading (Multithreading) |
Example: Complete Book Equality
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.