Browse Clojure Foundations for Java Developers

Implementing Immutability in Java vs Clojure

Why immutability is harder to enforce in Java, and what Clojure gives you by default.

Java can be written in an immutable style, but it takes discipline and conventions: immutable classes, defensive copies, unmodifiable wrappers, and careful API design.

Clojure flips the default: the standard collections and idioms assume immutability, and “updates” are expressed as functions that return new values.

What changes in practice

  • In Java, you often fight the type system and library defaults to keep data from being mutated.
  • In Clojure, you mostly fight the opposite problem: deciding where mutation is actually necessary (usually at the edges or in controlled state references).

Practical guidance: even if you love immutability in Java, do not try to recreate Java’s patterns in Clojure. Learn the persistent collection operations and let the language carry more of the burden.

In this section

  • Immutability in Java
    See what Java teams have to build manually to get trustworthy immutable models, and why that discipline still matters when moving to Clojure.
  • Immutability by Default in Clojure
    Learn what Clojure gives you automatically, what still stays explicit, and why value semantics feel lighter than Java's defensive-copy style.
  • Case Study: Refactoring Java Code
    Refactor a mutable Java order model into Clojure value transformations, and see where state, rules, and side effects land afterward.
Revised on Friday, April 24, 2026