Make immutable Java object

How do you make a mutable object immutable?

  1. Declare the class as final so it can’t be extended.
  2. Make all fields private so that direct access is not allowed.
  3. Don’t provide setter methods for variables
  4. Make all mutable fields final so that it’s value can be assigned only once.
  5. Initialize all the fields via a constructor performing deep copy.
  6. Perform cloning of objects in the getter methods to return a copy rather than returning the actual object reference.

source

Why do we create immutable objects?
Immutable objects are simply objects whose state (the object's data) cannot change after construction.

  • Security: store sensitive pieces of information like usernames, passwords, connection URLs, network connections etc.
  • are simple to construct, test, and use
  • are automatically thread-safe and have no synchronization issues
  • don't need a copy constructor
  • don't need an implementation of clone
  • allow hashCode to use lazy initialization, and to cache its return value
  • don't 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

Source

In Java, Strings are immutable, which provides, such as caching, security, easy reuse without replication, etc. Source


There are few things that you must consider for making an immutable class:

  • Make your class final - You already have
  • Make all the fields private and final - Make appropriate changes in your code
  • Don't provide any methods that change the state of your instance
  • If you have mutable fields in your class, like List, or Date, making them final won't suffice. You should return a defensive copy from their getters, so that their state isn't mutated by calling methods.

For the 4th point, say you have a Date field in your class, then the getter for that field should look like:

public Date getDate() {
    return new Date(this.date.getTime());
}

Making a defensive copy can become a headache, when your mutable field itself comprises of some mutable field, and that in turn can contain some other mutable field. In that case, you would need to make copy of each of them iteratively. We name this iterative copy of mutable fields as Deep Copy.

Implementing deep copy by yourself may be cumbersome. But,keeping that issue apart, you should consider your class design again, once you see yourself falling into such requirement of making deep defensive copy.


Your class is not immutable strictly speaking, it is only effectively immutable. To make it immutable, you need to use final:

private final String name;
private final String age;

Although the difference might seem subtle, it can make a significant difference in a multi-threaded context. An immutable class is inherently thread-safe, an effectively immutable class is thread safe only if it is safely published.