Back to Object Class & Constructors
Q5Question 5 of 5

What do the Object methods beyond equals/hashCode do?

Key Concepts
  • Every Java class inherits 11 methods from java.lang.Object
  • getClass() returns the runtime Class object, useful for reflection and exact type checking
  • clone() creates a shallow copy; requires the Cloneable marker; prefer copy constructors in production
  • wait()/notify()/notifyAll() enable inter-thread communication on the object's intrinsic monitor lock
  • wait/notify must be called inside synchronized because they manipulate the object's monitor lock
  • finalize() is deprecated since Java 9; use AutoCloseable with try-with-resources or Cleaner instead

Definition

getClass() returns runtime type. clone() creates a shallow copy (needs Cloneable). wait/notify enables thread communication on the object's monitor (must be in synchronized). finalize() is deprecated (use Cleaner or try-with-resources).

java.lang.Object has 11 methods that every Java class inherits.

  • getClass(): returns the runtime Class object. Useful for reflection, logging, and exact type checking (getClass() == SavingsAccount.class checks exact type, unlike instanceof which includes subclasses).
  • clone(): creates a shallow copy. Requires the Cloneable marker interface. Returns Object (must cast). Discouraged: prefer copy constructors.
  • wait() / notify() / notifyAll(): inter-thread communication using the object's intrinsic monitor lock. wait() releases the lock and suspends the thread. notify() wakes one waiting thread. Must be called inside synchronized because they manipulate the monitor lock: without the lock, IllegalMonitorStateException.
  • finalize(): called by GC before reclaiming the object. Deprecated since Java 9: unreliable, slow, can resurrect objects. Use AutoCloseable + try-with-resources or Cleaner instead.

getClass() is like checking which type of account this is at runtime. clone() is photocopying the account file (shallow: shared address card). wait/notify is the producer-consumer pattern: the teller (producer) says next customer, please (notify). The customer (consumer) says I will wait until called (wait). Both must hold the same ticket counter lock (synchronized). finalize() is the old janitor who cleaned up after closing hours: retired (deprecated). Use the new cleaning service (Cleaner/try-with-resources).

Understanding the Concepts

What do the Object methods beyond equals/hashCode do?

Every Java class inherits 11 methods from Object. Beyond equals/hashCode/toString, four important groups exist.

What does getClass() do?

JAVA
Account ref = new SavingsAccount("SAV001", java.math.BigDecimal.ZERO);

Class<?> cls = ref.getClass();
cls.getName();        // "com.bank.SavingsAccount" (actual type, not variable type)
cls.getSimpleName();  // "SavingsAccount"
cls.getSuperclass();  // Account.class

// Exact type check (no subclasses):
if (ref.getClass() == SavingsAccount.class) { /* exact match only */ }
// vs instanceof (includes subclasses):
if (ref instanceof Account) { /* SavingsAccount passes too */ }

// getClass() is final: cannot be overridden.

What does clone() do?

JAVA
public class Trade implements Cloneable {
    @Override
    public Trade clone() {
        try {
            return (Trade) super.clone(); // shallow copy
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(); // never happens: we implement Cloneable
        }
    }
}
// clone() is protected on Object: must override as public.
// Without Cloneable: CloneNotSupportedException.
// Discouraged: prefer copy constructors or records.

What do wait/notify/notifyAll do?

JAVA
public class TradeQueue {
    private final java.util.Queue<Trade> queue = new java.util.LinkedList<>();
    private static final int MAX = 10;

    public synchronized void produce(Trade trade) throws InterruptedException {
        while (queue.size() == MAX) {
            wait(); // queue full: release lock, suspend this thread
        }
        queue.add(trade);
        notifyAll(); // wake up all waiting consumers
    }

    public synchronized Trade consume() throws InterruptedException {
        while (queue.isEmpty()) {
            wait(); // queue empty: release lock, suspend this thread
        }
        Trade trade = queue.poll();
        notifyAll(); // wake up all waiting producers
        return trade;
    }
}

// Why synchronized is required:
// wait() releases the object's monitor lock. If you do not hold the lock, there is nothing to release.
// Without synchronized: IllegalMonitorStateException at runtime.

Why is finalize() deprecated?

JAVA
// OLD (deprecated since Java 9):
@Override
protected void finalize() throws Throwable {
    closeConnection(); // unreliable: no guarantee when or if GC calls this
}

// NEW: use AutoCloseable + try-with-resources
public class DbConnection implements AutoCloseable {
    @Override
    public void close() {
        connection.close(); // deterministic cleanup
    }
}
try (var conn = new DbConnection()) {
    // use conn
} // close() called automatically, always

How do all Object methods compare?

| Method | Purpose | Can override? | Notes |
|--------|---------|--------------|-------|
| equals() | Value equality | Yes | Override with hashCode |
| hashCode() | Hash code for collections | Yes | Must be consistent with equals |
| toString() | String representation | Yes | Used by println, debugger |
| getClass() | Runtime type info | No (final) | Returns Class |
| clone() | Shallow copy | Yes | Requires Cloneable |
| wait() | Thread waits for notify | No (final) | Must be in synchronized |
| notify() | Wakes one waiting thread | No (final) | Must be in synchronized |
| notifyAll() | Wakes all waiting threads | No (final) | Must be in synchronized |
| finalize() | GC cleanup | Yes | Deprecated since Java 9 |

What are common mistakes?

The most common mistake is calling wait() or notify() outside a synchronized block.

JAVA
// WRONG: not in synchronized
// trade.wait(); // IllegalMonitorStateException

// CORRECT: inside synchronized
synchronized(trade) { trade.wait(); }

What should a senior engineer know?

  • Modern concurrency uses java.util.concurrent (BlockingQueue, CountDownLatch, CompletableFuture) instead of raw wait/notify.
  • finalize() has been replaced by Cleaner (Java 9) and PhantomReference for GC-triggered cleanup.
  • getClass() is used in correct equals() implementations to prevent symmetry violations in inheritance hierarchies.

Visual Overview

DIAGRAM
  java.lang.Object (11 methods)
  ┌─────────────────────────────────────────┐
  │ IDENTITY & EQUALITY                      │
  │  equals(Object)  hashCode()  toString()  │
  ├─────────────────────────────────────────┤
  │ TYPE INFORMATION                         │
  │  getClass()  [final, cannot override]    │
  ├─────────────────────────────────────────┤
  │ COPYING                                  │
  │  clone()  [needs Cloneable marker]       │
  ├─────────────────────────────────────────┤
  │ THREAD COMMUNICATION                     │
  │  wait()  notify()  notifyAll()           │
  │  [all final, must be in synchronized]    │
  ├─────────────────────────────────────────┤
  │ CLEANUP (deprecated)                     │
  │  finalize()  [use Cleaner instead]       │
  └─────────────────────────────────────────┘

Key Takeaway

Every Java class inherits 11 methods from Object. Beyond equals/hashCode/toString: getClass() returns the runtime Class object for reflection and exact type checking. clone() creates a shallow copy requiring the Cloneable marker: discouraged in favor of copy constructors. wait/notify/notifyAll enable inter-thread communication: wait releases the object's monitor lock and suspends the thread; notify wakes one waiting thread. They must be called inside synchronized because wait releases the monitor lock and you must hold it first. Without synchronized: IllegalMonitorStateException. finalize() is deprecated since Java 9: use AutoCloseable with try-with-resources for deterministic cleanup.

Remember one sentence: every class inherits 11 methods from Object, and the key rules are that wait/notify must be in synchronized, clone needs Cloneable, getClass is final, and finalize is deprecated in favor of try-with-resources.

---

Share
Use ← → arrow keys to navigate