OOPS Interview Questions · Question 16

What is an immutable object, and what advantages can immutability provide?

Interview preparation resource from Gate Smashers.

Interview-ready answer

An immutable object is an object whose observable state cannot change after it is created. Instead of modifying the existing object, an operation that represents a change returns a new object. Immutability makes objects safer to share, easier to reason about, and suitable for stable equality and hash-based collections when their equality-relevant state is immutable.

Java immutable class examplejava
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public final class Person {
    private final String name;
    private final List<String> tags;

    public Person(String name, List<String> tags) {
        this.name = Objects.requireNonNull(name);
        this.tags = Collections.unmodifiableList(
            new ArrayList<>(Objects.requireNonNull(tags))
        );
    }

    public String getName() {
        return name;
    }

    public List<String> getTags() {
        return tags;
    }

    public Person withName(String newName) {
        return new Person(newName, tags);
    }

    public Person withAddedTag(String tag) {
        List<String> newTags = new ArrayList<>(tags);
        newTags.add(tag);
        return new Person(name, newTags);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;
        Person other = (Person) o;
        return name.equals(other.name) && tags.equals(other.tags);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, tags);
    }
}
Understand it clearly

Definition

An object is immutable when its externally observable state remains unchanged throughout its lifetime. Its fields may reference other objects, but those referenced objects must not allow the immutable object's observable state to be changed.

Advantages

Because an immutable object's state does not change, it can be shared without callers needing to coordinate updates. This reduces unintended side effects and makes code easier to understand, test, and use in concurrent programs.

  • Safer sharing: Immutable objects can be shared between threads without synchronization for changes to that object's state.
  • Simpler reasoning: A reference always represents the same value, which reduces bugs caused by unexpected mutation.
  • Stable map and set usage: An immutable object whose equals and hashCode depend only on immutable state is safe to use as a key in hash-based collections.
  • Caching and reuse: Instances can often be safely reused because their value does not change.
  • Functional style: Operations can return new values rather than modify existing ones, which supports composition and predictable behavior.

Implementing immutability

The exact mechanisms depend on the programming language. In languages such as Java, the class must prevent both direct field changes and indirect changes through mutable objects supplied by callers.

  • Prevent mutation: Do not expose setters or other methods that alter the object's state; return a new instance for value-changing operations.
  • Protect fields: Keep state private and initialize it during construction. In Java, fields are commonly declared final to prevent reassignment.
  • Defend mutable state: Copy mutable constructor inputs and avoid exposing mutable internal objects directly. Return copies or immutable representations when necessary.
  • Control inheritance: In Java, making the class final is a common way to prevent subclasses from weakening the immutability contract.

Trade-offs

Creating a new object for each logical change can increase allocation and copying costs, especially for large objects or frequent updates. Builders and data structures that share unchanged internal structure can reduce these costs when appropriate.