Java Language The recipe for an immutable class


Example

An immutable object is an object whose state cannot be changed. An immutable class is a class whose instances are immutable by design, and implementation. The Java class which is most commonly presented as an example of immutability is java.lang.String.

The following is a stereotypical example:

public final class Person {
    private final String name;
    private final String ssn;     // (SSN == social security number)

    public Person(String name, String ssn) {
        this.name = name;
        this.ssn = ssn;
    }

    public String getName() {
        return name;
    }
   
    public String getSSN() {
        return ssn;
    }
}

A variation on this is to declare the constructor as private and provide a public static factory method instead.


The standard recipe for an immutable class is as follows:

  • All properties must be set in the constructor(s) or factory method(s).
  • There should be no setters.
  • If it is necessary to include setters for interface compatibility reasons, they should either do nothing or throw an exception.
  • All properties should be declared as private and final.
  • For all properties that are references to mutable types:
    • the property should be initialized with a deep copy of the value passed via the constructor, and
    • the property's getter should return a deep copy of the property value.
  • The class should be declared as final to prevent someone creating a mutable subclass of an immutable class.

A couple of other things to note:

  • Immutability does not prevent object from being nullable; e.g. null can be assigned to a String variable.
  • If an immutable classes properties are declared as final, instances are inherently thread-safe. This makes immutable classes a good building block for implementing multi-threaded applications.