2014-09-14
Java unmodifiable vs. immutable vs. recursively immutable
During my current experiments with abstract polynomials for
Java, I thought that it would be good to implement them immutable
and so searched the Internet for an immutable list for Java. What
I found were blogs that
use immutable
and unmodifiable
synonymously, as well as at least one blog
which clearly makes the differences, as also explained in this stackoverflow
answer.
For the sake of clarity, let me try to define three related concepts:
- unmodifiable
- shall denote an object that has no has methods itself that change its state,
- immutable
- shall denote an object that is unmodifiable and, in addition, makes defensive shallow copies of incoming and outgoing objects stored in fields.
- recursively immutable
- shall denote an object that is immutable and has only fields with recursively immutable content. We leave perfidious changes to the object by reflection out of the picture.
The problem with Java is, that it cannot fit immutable objects
anymore into the collection framework. This gets most obvious from
Collections.singletonList()
. While
it returns an immutable list, as the documentation says, this list
can be considered broken, for the simple reason that it is
immutable. Although the List
interface clearly allows for operations on lists to throw an
UnsupportedOperationException
, this can lead
to bugs which are hard to debug. The list will be passed around in
the program from one place to the next and eventually some code
tries to add and element to the list, because this is what one
typically expects can be done with a list — booom, you
get an UnsupportedOperationException
out of
nowwhere. And it is even an unchecked exception, to be even more
surprising.
Making objects immutable by implementing an interface for
mutable objects only halfway and throwing
RuntimeException
s from the mutating methods really
looks like hack. Some people argue that to fix this, Java's
mutable collection interfaces need to inherit from immutable
ones. That would require to sneek an
ImmutableCollection
in as a parent interface of Collection. But
looking at the Scala
approach, this might not be needed. But a completely new
hierarchy of immutable colletions would indeed be necessary.