skip to content

java.lang.Object Methods Overview

The full set inherited from java.lang.Object, including which are final (getClass, wait, notify), which are protected (clone, finalize) and which are deprecated. A quick orientation question that sets up the contract discussions that follow.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

6

Every Java class implicitly inherits from java.lang.Object. Which methods does that give every object, and what is each for?

level: juniorimportance: must knowfreq 72%

answer

  1. equals/hashCode/toString = the override-trio
  2. getClass and wait/notify/notifyAll are final
  3. clone is protected + needs Cloneable
  4. finalize is deprecated since Java 9
  5. Object is the universal root, default equals = ==

basics

~10 s

Every object inherits from Object: equals (logical equality), hashCode (an int for hash collections), toString (a text form), getClass (its runtime class), clone (copying), the deprecated finalize, plus wait/notify/notifyAll for thread coordination.

solid answer

~40 s

In Java every class extends java.lang.Object directly or indirectly, so every object inherits a fixed set of methods. The everyday ones are equals(Object) for logical equality, hashCode() returning an int used by hash-based collections, and toString() for a human-readable representation; the defaults are identity-based, so you usually override these three together (equals/hashCode in tandem). getClass() returns the runtime Class object and is final. clone() (protected) makes a field-by-field copy but needs the Cloneable marker interface. finalize() was a pre-GC hook, now deprecated. wait(), notify() and notifyAll() are final methods for the intrinsic-lock wait/notify coordination protocol and must be called while holding the object's monitor. Knowing which are final, protected, or deprecated explains what you can and cannot override.

go deeper

for a junior

Can list the common inherited methods (equals, hashCode, toString) and knows every class extends Object.

for a middle

Knows the full set, which are final/protected/deprecated, and that default equals/hashCode are identity-based.

for a senior

Explains why each modifier exists (final protects runtime invariants, protected limits clone/finalize), and the override-together rule for equals/hashCode.

for a principal

Reasons about API/design implications: why a universal root constrains the type system, finalize deprecation toward Cleaner, and the monitor methods living on Object rather than a separate type.

## Why every object has these methods In Java, **`java.lang.Object`** sits at the very top of the class hierarchy. If you write `class Foo {}` with no `extends`, the compiler implicitly makes it `class Foo extends Object`. So *every* object — including arrays — inherits Object's methods. This guarantees a common minimum API that the JDK and frameworks can rely on (collections, debuggers, `System.out.println`, etc.). ## The inherited methods, one by one - **`public boolean equals(Object obj)`** — *logical equality*. The default implementation compares **references** (`this == obj`): two variables are equal only if they point to the very same object. Override it to define equality by content (e.g. two `Point(1,2)` instances being equal). - **`public int hashCode()`** — returns an `int` used to bucket the object in **hash-based collections** (`HashMap`, `HashSet`). The default derives a value from the object's identity. Rule: if two objects are `equals`, they **must** have the same `hashCode`, so you override the two together. - **`public String toString()`** — a textual representation. Default is `getClass().getName() + "@" + Integer.toHexString(hashCode())`, e.g. `com.acme.Point@1b6d3586`. Override to produce something readable; it is auto-invoked in string concatenation and `println`. - **`public final Class<?> getClass()`** — returns the **runtime** `Class` object describing the actual type. It is **`final`**, so you cannot override it — the JVM must report the true type for reflection and safety. - **`protected Object clone()`** — produces a *field-by-field (shallow)* copy. It is **`protected`** and only works if the class implements the **`Cloneable`** marker interface; otherwise it throws `CloneNotSupportedException`. Effective Java discourages it in favor of copy constructors/factories. - **`protected void finalize()`** — historically called by the garbage collector before reclaiming an object. **Deprecated since Java 9** (unpredictable, slow, can resurrect objects); replaced by try-with-resources and `Cleaner`. - **`public final void wait()` / `wait(long)` / `wait(long,int)`, `public final void notify()`, `public final void notifyAll()`** — the intrinsic-lock **wait/notify** thread-coordination protocol. They are **`final`** (the protocol is fixed) and must be called while holding the object's monitor (else `IllegalMonitorStateException`). ## Which are final / protected / deprecated, and why it matters | Method | Modifier | Can you override? | Note | |---|---|---|---| | `equals`, `hashCode`, `toString` | public | Yes | The three you normally override | | `getClass` | public **final** | No | Must report true runtime type | | `clone` | **protected** | Yes (often re-declared public) | Needs `Cloneable` | | `finalize` | protected, **deprecated** | Yes but don't | Use `Cleaner` instead | | `wait`/`notify`/`notifyAll` | public **final** | No | Monitor protocol is fixed | The modifiers encode design intent: `final` blocks overriding things the runtime depends on; `protected` limits casual external calls (clone, finalize); `deprecated` signals 'avoid'.

  • Why are wait/notify/notifyAll declared final on Object?
    They implement the JVM's fixed monitor wait-set protocol tied to every object's intrinsic lock; allowing overrides could corrupt that contract, so the language forbids it.
  • Which Object methods are most commonly overridden in practice?
    equals, hashCode and toString. equals and hashCode are overridden together to keep their contract; toString is overridden for readable logging/debugging.

saying these in an interview costs you the question

  • Claiming you can override getClass() or wait()/notify() (they are final)
  • Saying clone() works on any class without implementing Cloneable
  • Thinking finalize() reliably frees resources at a known time
  • Overriding equals() but not hashCode() (breaks hash collections)
  • Assuming default equals() compares contents rather than references

context

open as a page

What does Object.toString() return by default, and why is that often unhelpful for logging?

level: juniorimportance: should knowfreq 58%

basics

~20 s

By default toString() returns the class name, an '@', and the hashCode in hex, like Point@1b6d3586. It is auto-called in println and string concatenation, but shows no field values, so logs look cryptic unless you override it.

open as a page

Why is Object.clone() protected and why does calling clone() on a class without Cloneable fail?

level: middleimportance: should knowfreq 55%

basics

~20 s

clone() is protected so it isn't a public API by default. Object.clone() checks for the Cloneable marker interface; without it, it throws CloneNotSupportedException. Cloneable carries no methods — it just flips clone() from throwing to copying.

open as a page

What does getClass() return, why is it final, and how does it differ from instanceof for type checks?

level: middleimportance: should knowfreq 50%

basics

~20 s

getClass() returns the exact runtime Class of an object. It's final so the JVM always reports the true type. getClass() matches only the exact class; instanceof matches the class and any subtype, so instanceof is more permissive.

open as a page

Why was finalize() deprecated, and what should you use instead for resource cleanup?

level: seniorimportance: should knowfreq 48%

basics

~20 s

finalize() ran before garbage collection with no timing guarantee, was slow, and could even resurrect objects, so it was unreliable for cleanup. It's deprecated since Java 9. Use try-with-resources (AutoCloseable) for deterministic cleanup, and Cleaner as a safety net.

open as a page

Why do wait(), notify() and notifyAll() live on java.lang.Object rather than on Thread, and what rule governs calling them?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Every Java object has an intrinsic lock (monitor) and an associated wait-set, so the wait/notify methods belong on Object — the thing being locked. You must call them while holding that object's monitor (inside synchronized), or you get IllegalMonitorStateException.

open as a page