How to make immutable class in Java

Java documentation itself has some guidelines identified to write immutable classes. We will try to understand what these guidelines mean actually by creating an immutable class with mutable object with Date field.

A Strategy for Defining Immutable Objects The following rules define a simple strategy for creating immutable objects. Not all classes documented as "immutable" follow these rules. This does not necessarily mean the creators of these classes were sloppy — they may have good reason for believing that instances of their classes never change after construction. However, such strategies require sophisticated analysis and are not for beginners.

Don't provide "setter" methods — methods that modify fields or objects referred to by fields.

Make all fields final and private.

Don't allow subclasses to override methods -The simplest way to do this is to declare the class as final.

A more sophisticated approach is to make the constructor private and construct instances in factory methods.

If the instance fields include references to mutable objects, don't allow those objects to be changed:

Don't provide methods that modify the mutable objects.

Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.

Applying this strategy to SynchronizedRGB results in the following steps:

There are two setter methods in this class. The first one, set, arbitrarily transforms the object, and has no place in an immutable version of the class. The second one, invert, can be adapted by having it create a new object instead of modifying the existing one. All fields are already private; they are further qualified as final. The class itself is declared final. Only one field refers to an object, and that object is itself immutable. Therefore, no safeguards against changing the state of "contained" mutable objects are necessary.

Don’t provide “setter” methods — methods that modify fields or objects referred to by fields. This principle says that for all mutable properties in your class, do not provide setter methods. Setter methods are meant to change the state of an object and this is what we want to prevent here.

Make all fields final and private This is another way to increase immutability. Fields declared private will not be accessible outside the class and making them final will ensure the even accidentally you can not change them.

Don’t allow subclasses to override methods The simplest way to do this is to declare the class as final. Final classes in java can not be extended.

Special attention when having mutable instance variables Always remember that your instance variables will be either mutable or immutable. Identify them and return new objects with copied content for all mutable objects. Immutable variables can be returned safely without extra effort.

A more sophisticated approach is to make the constructor private and construct instances in factory methods.

Immutable classes in JDK Apart from your written classes, JDK itself has lots of immutable classes. Given is such a list of immutable classes in Java.

Let's first identify the advantages of immutable class. In Java, immutable classes are:

String

Wrapper classes such as Integer, Long, Double etc.

Immutable collection classes such as Collections.singletonMap() etc.

java.lang.StackTraceElement

Java enums (ideally they should be)

java.util.Locale

java.util.UUID

Benefits of making a class immutable

are simple to construct, test, and use are automatically thread-safe and have no synchronization issues do not need a copy constructor do not need an implementation of clone allow hashCode() to use lazy initialization, and to cache its return value do not need to be copied defensively when used as a field make good Map keys and Set elements (these objects must not change state while in the collection) have their class invariant established once upon construction, and it never needs to be checked again always have “failure atomicity” (a term used by Joshua Bloch) : if an immutable object throws an exception, it’s never left in an undesirable or indeterminate state

Summary

In this article, we learned to create an immutable java class with mutable objects as well as immutable fields as well. We also saw the benefits which immutable classes bring in an application.

As a design best practice, always aim to make your application Java classes to be immutable. In this way, you can always worry less about concurrency-related defects in your program.

Happy Learning!!