Java Immutable Classes: Definitive Guide

First of all, let’s define what is an immutable object in Java.

It’s one of the most popular interview questions.

An immutable object is an object that constructed once and can’t be changed in future.

How to create an immutable class in Java?

You should follow rules:

  • Make fields private and final.
  • Make class final to prohibit inheritance.
  • Don’t create setters or any other methods, that can modify fields.
  • If field refers to a mutable object you should not allow to modify it as well – getter or any other method should return a deep copy of that object.

Example:

package com.explainjava;
 
public final class Car {
 
    private final String color;
    private final Engine engine;
 
    public Car(String color, Engine engine) {
        this.color = color;
        this.engine = new Engine(engine.getName());
    }
 
    public String getColor() {
        return color;
    }
 
    public Engine getEngine() {
        return new Engine(engine.getName());
    }
}

Note that I create a new Engine() object in the getter and in the constructor to protect it.

Another way to go is to implement Cloneable interface and use clone() method.

What are advantages of immutable classes?

  • Thread-safe: it’s easier to synchronize and parallelize your program.
  • It’s a good choice for a key in HashMap or element of the HashSet because hash code cannot be changed.
  • Better security: for example, network connections, database connection URL, usernames/passwords are strings, developers don’t want to let them change easily, that’s why Java string is immutable.

Programmers usually worry about the cost of creating a new object instead of updating object fields in place.

The documentation says that impact of object creation is often overestimated.

Keep reading and I’ll provide more immutable class examples in Java, explain what is immutable collections and give you a tip how to build immutable objects faster.

Immutable in Java

It’s one more popular interview question: “could you list a Java immutable classes?”.

I already mentioned string immutable class as an example.

What else?

  • Wrapper classes of primitive types: Integer, Long, Boolean, Character etc.
  • Locale
  • UUID
  • LocalDate, LocalTime and LocalDateTime
  • Optional

It’s just a small list of classes that provides immutability in Java.

How To Create Immutable Collections in Java?

First of all, what is an immutable collection?

It’s collection where you can’t add or delete elements.

Take a look at java.util.Collections class.

It provides a list of methods to create immutable collections:

  • public static <T>List<T>unmodifiableList (List<? extends T>list)
  • public static <K,V>Map<K,V>unmodifiableMap (Map<? extends K,? extends V> m)
  • public static <K,V>NavigableMap<K,V>unmodifiableNavigableMap (NavigableMap<K,? extends V>m)
  • public static <T>NavigableSet<T>unmodifiableNavigableSet (NavigableSet<T>s)
  • public static <T>Set<T>unmodifiableSet (Set<? extends T> s)
  • public static <K,V>SortedMap<K,V>unmodifiableSortedMap (SortedMap<K,? extends V>m)
  • public static <T>SortedSet<T>unmodifiableSortedSet (SortedSet<T>s)

It’s really simple to use – provide a collection (List, Set, Map) as an input parameter and get an immutable collection as an output.

Collections class provides methods that return empty collections, it’s immutable as well:

  • public static <T>Enumeration<T> emptyEnumeration ()
  • public static <T>Iterator<T>emptyIterator ()
  • public static <T>List<T>emptyList ()
  • public static <T>ListIterator<T>emptyListIterator ()
  • public static <K,V>Map<K,V>emptyMap ()
  • public static <K,V>NavigableMap<K,V>emptyNavigableMap ()
  • public static <E>NavigableSet<E>emptyNavigableSet ()
  • public static <T>Set<T>emptySet ()
  • public static <K,V>SortedMap<K,V>emptySortedMap ()
  • public static <E>SortedSet<E>emptySortedSet ()

There 3 methods for single element collection in java.util.Collections:

  • public static <T>Set<T>singleton (T o)
  • public static <T>List<T>singletonList (T o)
  • public static <K,V>Map<K,V>singletonMap (K key, V value)

and it’s immutable as well.

When you’re converting an array to list Arrays.asList(arr) you’re getting immutable list.

Since Java 9 collection interfaces provide methods of() that build immutable collections.

Examples:

  • static <E>List<E>List.of(E…)
  • static <E>Set<E>Set.of(E…)
  • static <K,V>Map<K,V>Map.of(K,V)

This API looks similar to google guava collections API.

Guava provides an amount self-built immutable collections like ImmutableList, ImmutableSet, ImmutableMap etc.

You can follow the link above and read about all of them.

Lombok Immutable Class Syntax Sugar

Lombok project is a library that tries to beautify Java code, make it cleaner and shorter.

It can replace this 20 lines of code:

package com.explainjava;
 
public final class Car {
 
    private final String color;
    private final int year;
 
    public Car(String color, int year) {
        this.color = color;
        this.year = year;
    }
 
    public String getColor() {
        return color;
    }
 
    public int getYear() {
        return year;
    }
}

With just 10 lines that include @Value Lombok annotation on the class level:

package com.explainjava;
 
import lombok.Value;
 
@Value
public class Car {
 
    String color;
    int year;
}

Looks awesome!

@Value annotation automatically adds:

  • final to the class.
  • private and final to fields.
  • getters.
  • toString(), equals() and hashCode() methods.
  • constructor for all arguments.

Note that Lombok doesn’t know how to clone mutable objects, that’s why you should write this code manually.

Any question about immutability in Java? Ask me.

Leave a Comment