Mutable and Immutable Objects

by David O'Meara

Mutable and Immutable objects are a simple idea with wide ranging
consequences. Often when immutability is mentioned it isn't defined, or
when it is defined there are no details of how to ensure immutability or
the consequences.

Before we start, the terminology follows the article Pass-by-Value,
Please in the JavaRanch Camp fire. If you haven't
learnt to say Java is pass-by-value, you might want to head there
first.

Crappy Definition to start off with:

Mutable Objects: When
you have a reference to an instance of an object, the contents of that
instance can be alteredImmutable Objects: When you have
a reference to an instance of an object, the contents of that instance
cannot be altered

Immutability and Instances

To demonstrate this behaviour, we'll
use java.lang.String as the immutable
class and java.awt.Point as the
mutable class.

We are only looking at a single instance of each object,
but we can see that the contents of myPoint has changed, but the contents of myString did not. To show what happens when
we try to change the value of myString, we'll extend the previous example.

Now we find that the value displayed by the myString variable has changed. We have
defined immutable objects as being unable to change in value, so what is
happening? Let's extend the example again to watch the myString variable closer.

What this shows is that variable myString is referencing a new instance of the String class. The contents of the object
didn't change; we discarded the instance and changed our reference to a
new one with new contents.

Variable Values and Instance Contents

If you look at the example
above, you can see the point I'm trying to sneak through. You can always
change the value of a variable by getting your variable to reference a new
object. Sometimes you can change the value of a variable by keeping a
reference to the same instance, but change the contents of the instance.

After you have eliminated those possibilities, you have a variable that
retains its reference to an object, but the contents of this object cannot
change. Doesn't sound like a very interesting idea, and it sounds a bit
too simple to be useful.

It turns out that Immutable Objects, that is objects that you cannot
change the contents after they have been set, are a very handy tool when
used in the right place. They can promote thread safety in your code, you
can share them around without being afraid that they will change without
your knowledge, they are great for caching and constants. But we're not
going to cover any of that yet; we are going to concentrate on building
immutable objects.

Building an Immutable class

So what is it about the String class that makes it Immutable while a
Point is mutable?

In this case, Strings have no
mutators while Points do. If we
removed all of the mutators from the Point class, would it be Immutable? No it wouldn't.
Removing mutators is a necessary first step, but immutability requires
more than that to ensure that the contents of an instance never changes.

Fields must be private

Obviously all of the fields must be
private. There is little point removing the mutators if they aren't even
required to change the instance contents.

Make sure methods can't be overridden.

If your class gets
extended, it could add extra fields that are not immutable, or the methods
could be overridden to return a different value each time. There are two
ways to protect against this.

The preferred way is to make the class final. This is sometimes
referred to as "Strong Immutability". It prevents anyone from extending
your class and accidentally or deliberately making it mutable.

The second way, also called "Weak Immutability" is to make your methods
final. It allows others to extend your class to add more behaviour, but
protects the original contract specified by the class. If you want a more
verbose description, imagine a class A
is weakly immutable. If you have an instance of object A, it is immutable. If someone creates class
B that extends A, it is only the behaviour defined by the A class that is immutable. Any added
behaviour from class B may not be
immutable.

Protect mutable fields

The last requirement which many people fall
victim too, is to build your immutable class from primitive types or
immutable fields, otherwise you have to protect mutable fields from
manipulation.

To highlight this problem, we'll use the example of a supposedly
immutable class representing a person. Our class has a first and last
name, as well as a date of birth.

Depending
on the dates entered, the output could be something like this:

Mon Mar 24 21:34:16 GMT+08:00 2003
Thu Apr 24 21:34:16 GMT+08:00 2003

The Date object is mutable, and the myPerson variable is referencing the same instance of the
Date object as the myDate variable. When myDate changes the instance it is referencing, the myPerson instance changes too. It isn't
immutable!

We can defend against this by taking a copy of the of the Date instance when it is passed in rather
than trusting the reference to the instance we are given.

We
see here that taking a copy on the way in wasn't enough; we also need to
prevent anyone from getting a reference to our mutable Date field when we pass it out.

public Date getDOB()
{
return new Date( this.dob.getTime() );
}

Make deep copies of mutable data

The only point to add is that
when you copy the instance on the way in and the way out, you need to make
a deep copy. Otherwise you run the risk of leaving some mutable data in
your immutable class!

If you are confused about the need to provide a deep copy, keep in mind
that a single piece of shared mutable data, no matter how deep it is
buried inside an object, makes your class mutable. When you create a copy
of an object to defend against the value changing, you need to make sure
your copy doesn't include this shared mutable class. You need to copy any
mutable objects all the way down to the last field, and copy any nested
fields until you have a completely new copy of your own. It's the only way
to be safe!

Our Template for Immutable Classes

Now we have a template for
creating immutable objects.

Make all fields private

Don't provide mutators

Ensure that methods can't be overridden by either making the class
final (Strong Immutability) or making your methods final (Weak
Immutability)

If a field isn't primitive or immutable, make a deep clone on the
way in and the way out.

Which classes are Immutable?

To finish up, lets discuss the common
Java classes that are immutable and those that aren't. Firstly, all of the
java.lang package wrapper classes are
immutable: Boolean, Byte, Character, Double,
Float, Integer, Long, Short, String.

As in the Person classes we discussed, java.util.Date objects are not immutable. The classes java.math.BigInteger and BigDecimal are not immutable either,
although maybe they should have been.

And we're done...

...for now. This concludes an introduction to
Mutable and Immutable Classes in Java. Hopefully there will be a second
part that will go into more detail on weak and strong immutability,
reasons why you'd make classes immutable and reasons to avoid them, and
some other miscellaneous topics on immutable types in Java.