How do you design a correct immutable class for a multi-threaded service?
Reviewed by Gurusankar M.
Short Answer
Make the class final, all fields private final, no setters, initialize in the constructor, and defensively copy any mutable inputs/outputs (collections, dates). Java records do most of this — but you must still deep-copy mutable members.
On this page
Concept Made Simple
Coffee Chat Question
“How do you design a correct immutable class for a multi-threaded service?”
Remember It Faster
Mind Map Answer
- final class
- no subclass can add mutability
- private final fields
- set once
- no setters
- no post-construction change
- defensive copy
- in (ctor) and out (getters)
Learn by Doing
Hands-on Keyboard
public final class Money {
private final long cents;
private final List<String> tags;
public Money(long cents, List<String> tags) {
this.cents = cents;
this.tags = List.copyOf(tags); // defensive copy in
}
public List<String> tags() { return tags; } // already unmodifiable
}Think Beyond the Expected
What If?
A record holds a List field — is it truly immutable?
No. The record reference is final, but the List itself is still mutable, so callers can change its contents. You must copy it in the compact constructor (List.copyOf) and expose an unmodifiable view.
Real World
Immutable value objects (Money, DateRange, Coordinates) are shared freely across threads with zero synchronization — the backbone of thread-safe domain models and functional-style services.
Interviewer's Expectation
Keywords they're listening for:
- final class/fields
- no setters
- defensive copies of mutable members
- records caveat
- thread-safety benefit
Common Mistakes
- Storing a mutable collection/date without copying
- Returning the internal mutable reference from a getter
- Forgetting final on the class, allowing a mutable subclass
Best Practices
- Defensive-copy mutable inputs and outputs
- Prefer records + List.copyOf for value objects
- Provide with-style copy methods for 'changes'
Follow-up Questions
- How do records help, and where do they fall short?
- How do you 'modify' an immutable object (with-er / copy)?
- Why are immutable objects inherently thread-safe?
Continue Learning with AI
Take this question deeper with your favourite AI assistant. Pick a depth, copy the prompt, or open it directly — AI is your learning companion, not a shortcut.
Plain-language foundations
I'm preparing for a software engineering interview and want to understand this from scratch, as a beginner. Topic: OOP (Core Java) Interview question: "How do you design a correct immutable class for a multi-threaded service?" Please: 1. Explain the core idea in simple, plain language, using an everyday analogy. 2. Define any technical terms you use. 3. Walk through one small, concrete example. 4. Finish with a single sentence I can easily remember. Keep the tone friendly and assume I'm new to this topic.
Was this answer helpful?
Affiliate links
Tools for Your Developer Workspace
Equipment for a comfortable, productive setup.
As an Amazon Associate I earn from qualifying purchases.
- MonitorView on Amazon : BenQ EW2790U 27-inch Monitor (opens in a new tab)
BenQ EW2790U 27-inch Monitor
- LaptopView on Amazon : Acer Aspire One Laptop (opens in a new tab)
Acer Aspire One Laptop
- Office ChairView on Amazon : Wakefit Gravita Ergonomic Office Chair (opens in a new tab)
Wakefit Gravita Ergonomic Office Chair