Lesson Completion
Back to course

Immutable Classes: The Unbreakable Fortress

Beginner
10 minutes4.7Java

1. The Hook (The "Byte-Sized" Intro)

In a Nutshell: An Immutable Class is a class whose objects cannot be modified after creation. Once you create an immutable object, its state is locked forever—like writing with permanent ink. This makes code safer, thread-safe, and easier to reason about.

Think of a Bitcoin transaction. Once recorded on the blockchain, it's immutable—you can't change the amount or recipient. Java's String class works the same way: every "modification" actually creates a new String object!


2. Conceptual Clarity (The "Simple" Tier)

💡 The Analogy: The Diamond

Imagine a diamond.

  • Mutable Object: Like clay—you can reshape it, add to it, or remove parts.
  • Immutable Object: Like a diamond—once cut and polished, its structure is permanent. You can't "modify" it; you can only create a new diamond.

Hand-Drawn Logic Map

graph LR A[Create Object] --> B["Object State: Fixed"] B -.cannot modify.-> C["❌ No Setters"] B -.cannot modify.-> D["❌ No Mutable Fields"] B -.only option.-> E["Create New Object"] style B fill:#2E7D32 style E fill:#F57C00

3. Technical Mastery (The "Deep Dive")

Formal Definition

An Immutable Class is a class whose instances cannot be modified after creation. Requirements:

  1. No setter methods (no mutators).
  2. All fields are private and final.
  3. Class is final (cannot be subclassed).
  4. No mutable objects exposed (defensive copying).
  5. Initialization only via constructor.

The "Why" Paragraph

Why immutability? In multi-threaded applications, mutable objects are a nightmare—two threads can modify the same object simultaneously, causing race conditions. Immutable objects are inherently thread-safe (no synchronization needed). They're also easier to debug: if an object can't change, you don't have to hunt for the code that corrupted it. Java's entire String class is immutable for these exact reasons!

Visual Architecture: Immutability Chain

When you modify a String:

graph LR A["String s = 'Hello'"] --> B["Object: 'Hello'"] C["s = s + ' World'"] --> D["NEW Object: 'Hello World'"] B -.remains unchanged.-> B D -.s now points here.-> D style B fill:#D32F2F style D fill:#2E7D32

4. Interactive & Applied Code

The "Perfect" Code Block

java
// Immutable Class Example final class ImmutableUser { // 1. Class is final private final String name; // 2. Fields are private and final private final int age; private final Address address; // 3. Mutable object reference // 4. Constructor only public ImmutableUser(String name, int age, Address address) { this.name = name; this.age = age; // 5. Defensive copy of mutable object this.address = new Address(address.getCity(), address.getZip()); } // 6. Only getters (no setters!) public String getName() { return name; } public int getAge() { return age; } // 7. Return defensive copy, not original public Address getAddress() { return new Address(address.getCity(), address.getZip()); } } // Mutable helper class for demonstration class Address { private String city; private int zip; Address(String city, int zip) { this.city = city; this.zip = zip; } String getCity() { return city; } int getZip() { return zip; } void setCity(String city) { this.city = city; } } public class Main { public static void main(String[] args) { Address addr = new Address("NYC", 10001); ImmutableUser user = new ImmutableUser("Alice", 25, addr); // Try to modify the original address addr.setCity("LA"); // Original address changes System.out.println(user.getAddress().getCity()); // Still "NYC"! // Cannot modify user // user.setAge(26); // ❌ No such method! } }

The "Anti-Pattern" Example

❌ The "Leaky Abstraction" Mistake Exposing mutable internals breaks immutability:

java
class BadImmutable { private final int[] data; BadImmutable(int[] data) { this.data = data; // ❌ Storing reference to external array! } int[] getData() { return data; // ❌ Returning direct reference! } } int[] arr = {1, 2, 3}; BadImmutable obj = new BadImmutable(arr); arr[0] = 999; // ❌ Object's state just changed!

Fix: Use defensive copying:

java
this.data = arr.clone(); // Copy on construction return data.clone(); // Copy on retrieval

5. The Comparison & Decision Layer

Versus Table: Mutable vs. Immutable

FeatureMutableImmutable
Can ChangeYesNo
Thread-SafeNo (needs sync)Yes (inherently)
PerformanceBetter (in-place)Creates new objects
Use CaseFrequent updatesValue objects, keys
ExamplesStringBuilderString, Integer

Decision Tree: Should This Be Immutable?

graph TD A{Is this a value object?} A -- Yes --> B[Make Immutable] A -- No --> C{Used as HashMap key?} C -- Yes --> B C -- No --> D{Shared across threads?} D -- Yes --> B D -- No --> E[Mutable is OK]

6. The "Interview Corner" (The Edge)

The "Killer" Interview Question: "How do you create an immutable class in Java?" Answer: Follow these rules:

  1. Declare class as final.
  2. Make all fields private final.
  3. No setters—only constructor initialization.
  4. Use defensive copying for mutable object fields.
  5. Return copies, not references, from getters.

Bonus: Mention that String, all wrapper classes (Integer, Double), and LocalDate are immutable!

JVM/Performance Note

Memory Overhead: Creating new objects for every "modification" can seem wasteful. Java optimizes this with:

  • String Pool: Identical string literals share the same object.
  • Integer Cache: Small integers (-128 to 127) are cached.

Thread-Safety: Immutable objects eliminate the need for synchronized blocks, making multi-threaded code faster and simpler. This is why functional programming languages (Scala, Haskell) favor immutability.

Pro-Tip: Use immutable objects as HashMap keys:

java
Map<String, User> userMap = new HashMap<>(); // String is immutable ✅

If you use mutable objects as keys and modify them after insertion, the HashMap breaks—you can't find the key anymore!

Modern Java: Use Records (Java 14+) for concise immutable classes:

java
record User(String name, int age) { } // Auto-immutable! ✅

Topics Covered

Object-Oriented ProgrammingJava Fundamentals

Tags

#java#oop#classes#objects#encapsulation#interview-prep#beginner-friendly

Last Updated

2025-02-01