Immutable classes in Java

Photo by Emile Guillemot on Unsplash

Hi there!

Now we are going to talk about immutable classes in Java and show how to make the class immutable.

The class is called immutable if it is impossible to change its state and content after the initialization (creation).

The benefits of such classes are:

  • safety: you, as a developer, can be sure that no one is able to change their state;

So, let’s try to implement the immutable class by taking the mutable one and changing its implementation to the immutable step by step.

Consider, we have the following typical POJO class Hobbit:

Hobbit class has a field address of type Address:

Address class is not going to be changed in this article, so, in case of any questions, please reference to the embedded code above.

The first issue to be noticed is setters, that allow changing the value of each class field. So let’s remove those methods:

1. removing setters

Looks better, but now the user of our class has no chances to set the values to class fields. So, let’s provide the appropriate constructor:

2. adding all args constructor

Are we done now? Not yet, there are several issues left. First of all, our immutability could be hacked by using one of the OOP principles — inheritance. Let me demonstrate this with a simple example:

If we run the Hack class, we’ll get the following output:

Frodo BagginsImmutability has been hacked!Mr. Underhill

To fix this issue we have to:

3. marking class as final to protect it from being extended

Now if we run Hack class one more time, the output will be correct:

Frodo BagginsImmutability has been hacked!Frodo Baggins

There is one more interesting issue left: as we know, in Java when we pass the value of an object, we are passing the reference to it. So the state of the objects could be changed by the side effects. Let’s get back to the code to see this:

The output of this code is:

Hobbit country: Hobitton 
Hobbit city: Shire
Hobbit stuff: [Sword, Ring of Power]
Immutability has been hacked! Hobbit country: Isengard
Hobbit city: Saruman tower
Hobbit stuff: []

This issue could be fixed by:

4. initializing all non-primitive mutable fields via constructor by performing a deep copy

Now the output of Hack class is more predictable:

Hobbit country: Hobitton 
Hobbit city: Shire
Hobbit stuff: [Sword, Ring of Power]
Immutability has been hacked!Hobbit country: Hobitton
Hobbit city: Shire
Hobbit stuff: [Sword, Ring of Power]

But the same side effect issue could be produced through getter methods:

Output:

Hobbit country: Hobitton 
Hobbit city: Shire
Hobbit stuff: [Sword, Ring of Power]
Immutability has been hacked! Hobbit country: Isengard
Hobbit city: Saruman tower
Hobbit stuff: []

So, it goes with another step to be done:

5. performing cloning of the returned non-primitive mutable object in getter methods

Now the Hack output is:

Hobbit country: Hobitton 
Hobbit city: Shire
Hobbit stuff: [Sword, Ring of Power]
Immutability has been hacked!Hobbit country: Hobitton
Hobbit city: Shire
Hobbit stuff: [Sword, Ring of Power]

There is one more optional step to be done, but if all other prerequisites are met, it is not necessary. Anyway, let’s mentioned it:

6. marking all class fields as final (optional)

And that’s it, we are done — our Hobbit class is immutable now.

Let’s summarize out steps:

  1. removing setters;

Of course, there are other ways to make class immutable (for example, using Builder pattern), but it is out of the scope of the current story.

Have fun!

Software engineer: making the code great again

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store