Tuesday, September 15, 2009

Immutable Java Objects

Immutable objects are highly desirable. Because an immutable object's state cannot be changed, they are particularly useful in concurrent environments. Immutable options can simplify code and reduce chances of unanticipated and undesired state in objects.

I prefer that all of my Java classes provide for immutable objects unless there is a compelling need for them to be mutable. I'm not the only one who feels this way. In Effective Java (Item 15 ["Minimize Mutability"] in the Second Edition and Item 13 ["Favor Immutability"] in the First Edition), Joshua Bloch extols the virtues of immutable objects and emphasizes in bold text:

Classes should be immutable unless there's a very good reason to make them mutable.


Another proponent of immutable objects is Martin Odersky of Scala fame. He has stated about immutable objects:

we recommend that if you can make [objects] immutable, that's good, and you should try to find out where you can make objects immutable.


Conceptually, it sounds easy to create immutable objects. However, there are a couple nuances to note when ensuring that a Java class is defined so that its instantiated objects are immutable. Several resources outline the steps necessary to write a Java class that will lead to immutable Java objects. These resources include the previously mentioned Joshua Bloch Effective Java items on immutable objects. Other resources outlining the steps for making a Java object immutable include Java Practices, the Java Tutorials, JavaWorld's article Mutable or Immutable?, and developerWorks's To Mutate or Not to Mutate?.

Java classes that support immutable objects have the following characteristics:

• No "set" or mutator methods (object's state is set at instantiation/construction and cannot be changed later).

Implementation inheritance explicitly disallowed.

Fields are final and private.

• Its data members are either immutable or only provides access to defensive copies (also covered in Effective Java) of its mutable members.



As threading becomes more significant, immutable objects become more important. Trendy languages such as Scala and Clojure emphasize the importance of immutable data structures and immutable objects in their very design.

I have found that it works best for me to start with my objects as immutable objects and then only relax the immutability as absolutely necessary. This minimizes the mutability when it is required. In general, I resist the urge to "easily" use the IDE feature that quickly and thoughtlessly creates getter and setter methods for my new classes. I have found that it is better to think about how the class is used and only provide the mutability that is absolutely necessary.

3 comments:

Matt said...

"Implementation inheritance explicitly disallowed." -- isn't this largely orthogonal to the question of immutability?

Dustin said...

Matt,

Thanks for the message. That's a great question and I'll be posting another blog posting in the near future to attempt to address it.

Graham Allan said...

Hi,

I realise I'm way late to the discussion, but anyone who gets here via their favourite search engine may be interested in the following project:

https://github.com/MutabilityDetector/MutabilityDetector

It allows writing a unit test that checks your class is immutable. Disclaimer: I'm the author :)