An Introduction to Immutable Objects In Java

In this short tutorial we’ll examine and show how to create immutable objects in Java. Moreover, we will look at some of the benefits and drawbacks of immutable objects.

Why Use Immutable Objects

An Immutable Object in Java is an instance of a class, that does not allow its state to be mutated after it is instantiated. Normally, if an immutable object provides an operation that performs a mutation, this operation does not mutate the objects state, but instead returns a new version of the object.

For example if we look at the types that come as part of the new Java Date Time API, we can see that we are working with immutable types. If we want to perform a mutating operation on one of these types, the operation returns a new version of the temporal object, copying its internal state.

1
2
3
LocalDateTime newYearsEve = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59);

LocalDateTime newYearsDay = newYearsEve.plusMinutes(1);

In the above example after the plusMinutes method is executed a new instance of the LocalDateTime type is returned with its date / time adjusted to new years day.

Creating An Immutable Type In Java

To create an immutable object in Java, we need to ensure that the state of the object cannot be mutated after it is created.
To achieve this goal we will take advantage of the final keyword in Java. The final keyword can be applied to the different building blocks of a class, however for our purposes we will apply the final keyword to the constructs:

  • Class
  • Variables

Final Class

When a class is marked as final it is closed for extension. This means a subclass cannot override a method and modify its logic to behave in unexpected ways.

Final Variables

Marking instance variables of a class as final means that their values can not be modified after they are initialized.

We will now use these two options to create our immutable object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public final class ImmutablePoint {
    private final int x;
    private final int y;

    public ImmutablePoint(final int x, final int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

Notice that above we define all the instance variables of the class as final, to ensure that their values cannot be modified after they are initialized in the class constructor.

1
2
3
4
public ImmutablePoint(final int x, final int y) {
    this.x = x;
    this.y = y;
}

Moreover, we do not provide any mutator setter methods, that can cause a side effect changing the state of an instance.

Let’s consider that we would like to make our ImmutablePoint class more useful by moving the x coordinate.

1
2
3
4
5
6
7
8
9
public ImmutablePoint moveX(final int amount) {
    final int newX = x + amount;

    if (newX < 0) {
        throw new IllegalArgumentException("X cannot be less than zero, after move");
    }

    return new ImmutablePoint(newX, getY());
}

Look at the above code carefully, instead of mutating the x coordinate, we create a new instance of the ImmutablePoint class with the new value of the x coordinate.

Although we have created an immutable object, it is worth mentioning that it is still possible to change the internal state of the object through the Java Reflection API if the Java security manager permits it.

Benefits Of Immutable Objects

In the previous section we looked at how to create an immutable object in Java. Moreover, you are probably wondering why you might want to do this.

Well, immutable objects have a number of benefits:

  • Simplify writing concurrent programs.
  • They are functional programming friendly.
  • They make it easier to reason about our code.
  • Facilitate less imperative and more declarative code.
  • May reduce bugs.

Drawbacks Of Immutable Objects

The biggest drawback of immutability comes at the cost of performance in certain situations. This is because copying objects can increase the memory footprint of an application and the time it takes to perform an operation.

Therefore care should be taken especially when working with large collections in Java.

Conclusion

In this short tutorial we introduced immutability in Java. We looked at what immutability is some of its benefits, drawbacks, and how to implement an immutable object in Java.