Back in October 1997 I gave a talk, “Java Patterns”, at the end of the BCS OOPS Patterns Day (a.k.a. PLUnK, for Pattern Languages United Kingdom). I later wrote up the talk’s patterns for the BCS OOPS Newsletter. I also created a page for one of the patterns, Immutable Value, on the original Wiki. When I attended my first full patterns conference, PLoP 98, there was time left over at the end of one of the workshops. I quickly printed off the Wiki page and had the pattern workshopped, the feedback from which I used to update the Wiki entry.
The old Wiki version of the pattern — plus this historical (p)r(e)amble and a coda discussion — is shown here with minor reformatting and punctuation edits.
Press enter or click to view image in full size
Abstract
Objects are often characterised by identity, behaviour and state. However, the relative importance between these can vary from problem to problem. Value patterns focus on those object patterns for which behaviour and state are more important than reference-based identity, i.e., the ability to distinguish one object from another by its identity is not as significant as the role played by its content, leading to a distinction between a value object and a reference object.
The Immutable Value pattern resolves a number of implementation and optimisation issues found in concurrent systems and in languages whose object models rely exclusively on reference semantics. Immutable Value can be considered one of the common Java idioms.
Context
- Small objects with simple construction for which distinct object identity is not important but value-based content is.
- A language, such as Java, that supports neither value-based semantics for user-defined types nor a way of specifying object immutability within the type system.
- Objects shared by reference between threads in a concurrent system.
Forces
- Attributes are instance variables that represent simple values rather than associations for an object, e.g., date of birth is an attribute of a person whereas their employer is an association. To avoid changes through other references when passing attributes around they must be copied, which may incur an inappropriate overhead.
- The integrity of an associative collection, such as a dictionary, may be compromised if the state of an object used as a key is modified via an aliasing reference.
- The required use of clone to copy objects that should not be aliased is potentially error prone, i.e., it is easy to forget, and it cannot be enforced automatically.
- Synchronisation of state change incurs an overhead, but is essential in guarding against race conditions and ensuring thread safety.
- It must be easy for the programmer to use different values, i.e. there should be no great cost in terms of the usage complexity.
Solution
- Make an object’s state immutable, i.e., freeze it at construction and ensure that all instance methods are queries.
- Provide an intuitive and complete set of constructors whose construction is lightweight.
Rationale
- By definition, the state of an immutable object cannot be changed, and hence will not suffer from undesirable or unpredictable change.
Resulting Context
- No need for synchronisation and no race condition problems.
- Sharing without aliasing side effects and therefore no need for copying.
- Change of value is effected by replacement with another object representing a different value.
- The class must be final or any given subclass must also be an Immutable Value.
- Much more dynamic memory allocation where values are changed often. If this incurs an undesirable overhead, the Flyweight pattern can be applied as an optimisation.
Examples and Related Concepts
- The standard java.lang.String class is a value-based class in the core of the language. It supports only construction and query methods and its instances may be shared without aliasing or threading problems. New strings are created directly with the public assistance of constructors, indirectly as the results of query methods, or via the use of the java.lang.StringBuffer class.
- Functional programming is based on pure mathematical values, which are immutable.
- In C++, many immutable values are often expressed directly using the const qualifier.
- In Ada, the equivalent is the use of the constant keyword.
- The Readonly Interface pattern, which is related to Immutable Interface, seeks to separate the modifier and query operations on a class into separate interfaces so that it is clear what role an object is permitted and intended to play when passed to another as a method argument. Such a technique enforces specification requirements more clearly in the type system. This can be considered to emulate many uses of const with references and pointers in C++, constant with access types in Ada 95, and READONLY with arguments in Modula-3. Although they are clearly related, there is a fundamental difference in intent between Immutable Value and Readonly Interface: Immutable Value addresses issues related to concurrency and aliasing for objects whose value but not identity is important; Readonly Interface addresses partitioning a class interface into separate interfaces based on method side effects to support finer grained specification of intent.
- Resolving the circle-and-ellipse problem (a.k.a. the square-and-rectangle-problem). This is the problem that comes from taking the apparently intuitive step from “a circle is a kind of ellipse” to having a circle inherit from an ellipse. Leaving aside the issue of redundant state in the subclass, this appears to present a problem when, given an ellipse that supports general resizing, a circle is stretched along an axis: it ceases to be a circle, and yet still retains the type of a circle. The resolution is to realise that the translation from “a circle is a kind of ellipse” is imperfect: “so long as it is not modified, a circle is a kind of ellipse”. Put another way, when ellipse and circle are modelled as immutable values the problem disappears. This illustrates that the problem is largely one of incorrect modelling: the domain of origina (mathematics) does not model circles and ellipses as referenced mutable entities!
The significance of immutability as a first-class programming is more widely recognised and embraced than it was in the 1990s and early 2000s. This is in part through greater awareness of declarative programming paradigms, such as functional programming, in the mainstream; the growing recognition that immutability offers a simpler, safer and more composable approach to working across threads; types whose instances were immutable making an appearance in common and core libraries; the inclusion of change-restriction features in languages, from simple const, final or readonly prevention of variable reassignment through to deeper restrictions, such as found in C++’s ever-growing family of const-related keywords, Java’s record types and Rust’s defaulting of variables to unassignable.
Similarly, there is also a greater recognition of the value of values (sic), where object identity is not considered significant to the way an object is used and should therefore be modelled, considered and coded differently to entity and mechanism abstractions. In the patterns space this includes Ward Cunningham’s Whole Value, Martin Fowler’s Quantity and Eric Evans’ Value Object pattern write-ups, as well Immutable Value. It can also be found in Michael Jackson’s classification of values, entities and events as distinct kinds of individual phenomena in the problem domain. In languages, value-based programming has also been represented more directly, although often from a mechanistic perspective, e.g., copyable rather than referenced objects.
There is much about both immutability and value-based programming that might appear obvious, but this is the benefit of progress coupled with the gift of hindsight:
- When workshopping this pattern at PLoP 98, a number of participants — deeply steeped in OO, Smalltalk, etc. — failed to initially grasp what the design message was and kept confusing Immutable Value with the Flyweight pattern. Familiarity creates a distorted lens through which we evaluate new concepts, one that may lead us to see one thing as another rather than either a feature of another or as a separate concept in its own right.
- At the end of a 2006 talk about object concurrency, a well-respected OO guru, language designer and researcher was floored when I asked why his proposed approach was all lock-based and immutability played no part. It simply hadn’t occurred to him. Familiarity creates a path dependency and can narrow our thinking. For decades, the dominant narrative around concurrency in academia and APIs was locks, locks and more locks.
It would also be wrong to assume that, because these ideas are out there and have been out there for a while, this in some way constitutes mainstream thinking. Yes, there is more awareness than there used to be, but both values and immutability are still considered secondary rather than first-class concepts — if they are considered at all. Over a decade and a half after writing it, when I extended and published “Restrict Mutability of State” on this blog, it still appeared to be news to many who came across it.
Republishing this old pattern with additional context and commentary is, I hope, useful as history, practical for now and another nudge, however small, for future.
.png)

![Claude Code modernizes a legacy COBOL codebase [video]](https://www.youtube.com/img/desktop/supported_browsers/edgium.png)