The first advantage of immutability is avoiding side effects. Let’s take a look at an example:
When we look at the signature of the method, it seems that everything is OK. The method takes a collection of doubles and returns an average. However, nothing prevents a developer from implementing the method in this way:
Therefore, this method is not a pure function. It doesn’t have a boundary between arguments and the result, because an argument is changed as well. In order to ensure nothing like that will happen we should pass an immutable collection.
Another reason why immutability is great is connected with different collections. Let’s assume that we have Point class:
What will happen if we put an instance of the Point class into HashMap and later on we change the value of x or y? Let’s check:
And this is the result:
After the point instance had been changed, the hashcode of that object was different, therefore it couldn’t be found in HashMap (a bucket not found). Similar side effects can be observed when it comes to using tree-based structures like TreeMap. Once an object was put in a structure. The order of objects is not changed if the object was modified. Because of that, it is highly recommended to use an immutable object as a key in map structures.
Another gain from immutability is the fact that we don’t need any more defensive copies. I’m pretty sure that a lot of programmers who remember java.util.Calendar and java.util.Date remember how they had to make a lot of copies of those objects. For instance, let’s assume that we need to create a DTO class which represents delivery data. And we have a field which tells us when we, a client, should expect items to be delivered. Usage of java.util.Date calendar will force us to create a defensive copy of the date. It’s because it can be used later on in some other computations.
Many people will say that creating immutable objects will lead to a garbage collector overhead. However, this is not true at all. The first reason is that we don’t need defensive copies. As I pointed out before. And it is much easier to delete an object from a heap than an old one. When we create a new object, which has almost all references as an old object and one or a few new references to new objects, it is better than having an older object which has references to new objects. We are also able to use an object pool and flyweight pattern to manage those value objects. We all know a very good example: String class.
The last benefit I would like to describe is thread safety – objects which are immutable are perfectly thread-safe. There are no race conditions on the mutating state of the object, and the final keyword ensures visibility for other threads.
Of course, there are areas where immutability is not the best option. The first of them is GUI – where mutation of a state and a graphical interface go naturally together. Sometimes we also need mutable objects when we use concurrency. For instance, the BlockingQueue class should be mutable in order to work correctly. Mutable data structures are often very useful when we need high performance. There are more situations when mutability is better than immutability. However, I still believe that immutability is great when it comes to proceeding data e.g. in business applications.
I hope I’ve persuaded you to change your way of thinking about using immutability and to take full advantage of its the benefits.