Immutable Objects in Java

Immutable objects are objects that cannot be changed once created.

For instance, String is an immutable class in Java.

Consider the code below, in the first line a new String object is created (“Hello”). In the second line, we are trying to change the String (“Hello World”).

    String str1 = "Hello";
    str1 += " World";

However, since the String class is immutable, existing String object cannot be updated. Rather a new String object is created and str1 points to this new object.

Java String Immutable Object

Other than String class, all wrapper classes in Java are immutable like Boolean, Double, Float, Integer, Long.

How to Create Immutable Class in Java?
To create immutable class you follow these steps:

  1. Make sure that the class cannot be overridden (i.e. declare the class as final, or make constructors private)
  2. Make all fields final and private
  3. Do not provide any setter methods (a.k.a. mutator methods)
  4. In getter methods (a.k.a. accessor methods), do not return actual object reference, instead return a copy of the object

Benefits of Immutable Objects
If we cannot change immutable objects, why do we need them?

There are several advantages of using immutable objects:

  1. Immutable objects are inherently thread-safe, you don’t need to synchronize immutable objects in multi threaded applications.
  2. Immutable objects can be used as keys in hashmaps.
  3. You can safely share references to immutable objects. You don’t need to copy or clone them when sharing because immutable objects cannot be changed.
  4. You don’t need defensive copying for immutable objects.

Drawbacks of Immutable Objects
There might be some performance issues if you make a lot of modifications on an immutable object. Because each time you modify an immutable object, a new object is created in memory. To overcome this problem you can use mutable object types for modification and convert it to an immutable object as the final step.

For instance consider the following code. A new String object is created every time allCountries is updated inside for loop.

    String allCountries = "";
    for (int i = 0; i < countries.size(); i++) {
      allCountries += countries.get(i);
    }

This code can be refactored as follows, so that only two objects are created. One StringBuilder object and one String object.

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < countries.size(); i++) {
      sb.append(countries.get(i));
    }
    String allCountries = sb.toString();

Line 3 above does not create a new StringBuilder object on each call, because StringBuilder is a mutable class, not an immutable class.

Related Subjects
Defensive Copying