How to create an immutable class in java

An object is immutable if its state cannot change after construction, immutable objects don’t expose any way for other objects to modify their state, the object’s fields are initialized only once inside the constructor and never change again.

In this article, we define the typical steps for creating an immutable class in java, we also shed the light on the common mistakes which are normally done by developers while creating immutable classes.

1. Usage of Immutable classes

Nowadays, the “must-have” specification of every software application is to be distributed and multi-threaded, multi-threaded applications always cause headache to developers since developers are required to protect the state of their objects from concurrent modifications of several threads at the same time, for this purpose, developers normally use the Synchronized blocks whenever they modify the state of an object.

With immutable classes, states are never modified, every modification of a state results in a new instance, hence each thread would use a different instance and developers wouldn’t worry about concurrent modifications.

2. Some popular immutable classes

String is the most popular immutable class in java,  once initialized its value cannot be modified, operations like trim(), substring(), replace() always return a new instance and don’t affect the current instance, that’s why we usually call trim() as the following:

Another example from JDK is the wrapper classes like: Integer, Float, Boolean … these classes don’t modify their state , however they create a new instance each time you try to modify them.

After calling a += 3, a new instance is created holding value: 6 and the first instance is lost.

3. How do we create an immutable class

In order to create an immutable class, you should follow the below steps:

  1. Make your class final, so that no other classes can extend it.
  2. Make all your fields final, so that they’re initialized only once inside the constructor and never modified afterwards.
  3. Don’t expose setter methods.
  4. When exposing methods which modify the state of the class, you must always return a new instance of the class.
  5. If the class holds a mutable object:
    • Inside the constructor, make sure to use a clone copy of the passed argument and never set your mutable field to the real instance passed through constructor,  this is to prevent the clients who pass the object from modifying it afterwards.
    • Make sure to always return a clone copy of the field and never return the real object instance.

3.1. Simple immutable class

Let’s follow the above steps and create our own immutable class (ImmutableStudent.java).

The above class is a very simple immutable class which doesn’t hold any mutable object and never expose its fields in any way, these type of classes are normally used for caching purposes.

3.2.  Passing mutable objects to immutable class

Now let’s complicate our example a bit, we create a mutable class called Age and add it as a field to ImmutableStudent:

So, we added a new mutable field of type Age to our immutable class and assign it as normal inside the constructor.

Let’s create a simple test class and verify that ImmutableStudent is no more immutable:

After running the above test, we get the following output:

We claim that ImmutableStudent is an immutable class whose state is never modified after construction, however in the above example we are able to modify the age of Alex even after constructing Alex object. If we go back to the implementation of ImmutableStudent constructor, we find that age field is being assigned to the instance of the Age argument, so whenever the referenced Age is modified outside the class , the change is reflected directly on the state of Alex. Check Pass by value OR pass by reference article to deeply understand this concept.

In order to fix this and make our class again immutable, we follow step #5 from the steps that we mention above for creating an immutable class. So we modify the constructor in order to clone the passed argument of Age and use a clone instance of it.

Now, if we run our test, we get the following output:

As you see now, the age of Alex is never affected after construction and our class is back immutable.

3.3. Returning mutable objects from immutable class

However, our class still have a leak and is not fully immutable, let’s take the following test scenario:

Output:

Again according to step #4, when returning mutable fields from immutable object, you should return a clone instance of them and not the real instance of the field.

So we modify getAge() in order to return a clone of the object’s age:

Now the class becomes fully immutable and provides no way or method for other objects to modify its state.

4. Conclusion

Immutable classes provide a lot of advantages especially when used correctly in multi-threaded environment, the only disadvantage is that they consume more memory than the traditional class since upon each modification of them a new object is created in the memory, but a developer should not overestimate the memory consumption as its negligible compared to the advantages provided by these type of classes.

Finally, an object is immutable if it can present only one state to the other objects, no matter how and when they call its methods. If so it’s thread safe by any definition of thread-safe.

 

husseinterek

Founder of programmergate.com, I have a passion in software engineering and everything related to java environment.

You may also like...

Leave a Reply

6 Comments on "How to create an immutable class in java"

avatar
Sort by:   newest | oldest | most voted
Khodor
Guest

Good one !

Bikram
Guest

By using private and final key word.

Ravindra Jha
Guest

Can you explain how can we make N nested objects immutable ? Is there any mechanism for that or we will have to make each object immutable.

Shivam Joshi
Guest

Nice

wpDiscuz