What are the advantages of immutable objects for caching?
Immutable objects are ideal for caching because their contents don't change.
Junior Level
Immutable objects are ideal for caching because their contents don’t change.
Advantages
- Safe return — can hand the object from cache directly, without making a copy
- Stable keys —
hashCodedoesn’t change, object won’t get “lost” in the cache - Multi-threaded access — multiple threads can read the cache simultaneously without locks
Example
// Immutable object — can be cached safely
public record Product(String id, String name, BigDecimal price) {}
Map<String, Product> cache = new ConcurrentHashMap<>();
cache.put("1", new Product("1", "Book", new BigDecimal("9.99")));
Product p = cache.get("1"); // safe — nobody can change p
Middle Level
Cache key stability
If an object is a key in the cache (HashMap, Caffeine, Redis):
- Its
hashCode()must be consistent - For an immutable object, the hash is computed once and never changes
- Risk with a mutable key: the object changes and gets “lost” in a different bucket → memory leak
Read-sharing safety
Immutable values can be returned from cache by reference:
- No defensive copy needed on each request
- Multiple threads work with the same instance without locks
- Without locks, threads don’t wait for monitors — no context switch, no park/unpark. Under read-heavy load, this gives linear scalability as core count increases.
Flyweight pattern
Immutability enables object reuse:
- String Pool — cache of string literals
- Integer Cache — numbers from -128 to 127
- One instance for all identical values
No cache “poisoning”
With a mutable object, one thread can get an object and modify it — this “poisons” the cache for everyone. Immutability guarantees that data remains pristine.
Senior Level
GC efficiency
Immutable objects in the cache end up in Old Generation. Since they don’t change, immutable objects don’t create new cross-generation references after creation, which simplifies GC work when scanning Old Generation.
Distributed caching
In Redis / Memcached:
- Immutable DTOs are safely serialized/deserialized
- No risk of the object changing during serialization
- Ideal for CQRS / Event Sourcing
Summary for Senior
- Immutability is the key to Lock-free cache access
- Prevents data corruption from side effects
- Deterministic key operations
- Using immutable DTOs and Records — best practice for caching systems
- Immutable objects don’t create cross-generation references, simplifying GC work
Interview Cheat Sheet
Must know:
- Safe return from cache — can return by reference, no copy needed
- Stable keys —
hashCodedoesn’t change, object won’t get “lost” in the bucket - Lock-free multi-threaded access — no locks, no context switch
- Flyweight pattern — reuse of identical objects (String Pool, Integer Cache)
- No cache “poisoning” — one thread cannot modify an object for everyone
- GC efficiency — no cross-generation references, simplifies Old Generation scanning
Frequent follow-up questions:
- Why is a mutable key dangerous in cache? — hashCode changes → object gets “lost” → memory leak
- Do I need a defensive copy when returning from cache? — No, immutable object can be returned by reference
- How does immutability help distributed caching? — Safe serialization, no risk of change during serialization
- What is cache “poisoning”? — One thread gets an object and changes it — “poisons” it for everyone else
Red flags (do NOT say):
- “Immutable objects can’t be cached” — they are IDEAL for caching
- “Need synchronization for reading cache with immutable objects” — lock-free access
- “Mutable key in HashMap is fine” — on change the object gets lost
- “Cache should always copy objects” — excessive for immutable ones
Related topics:
- [[2. What advantages do immutable objects provide]]
- [[23. How does immutability affect performance]]
- [[27. Can you use immutable objects as keys in HashMap]]
- [[28. What happens if you modify a mutable key in HashMap]]