Creating Immutable Class in Java


This article shows how to create immutable classes in Java, using suitable examples, for a better explanation.

Immutable class in Java

Immutable classes are those classes whose object's state cannot be changed, once created.  Any modification results in a new immutable object.
To better understand, let's use a simple example of String and StringBuffer classes.  In other words using a substring, concat, and so on, results in a new immutable object, when an operation is performed on the StringBuffer class but does not create a new immutable object. Instead, it reflects the changes in the existing object only. Even JDK itself contains a number of immutable classes, like String, Float, and other wrapper classes. We can also create an immutable class by creating a final class that has final data members.

Guidelines for making an immutable class in Java

The following are simple guidelines that can be followed to make a class immutable in Java:
  • Do not provide a setter method for the class, because setter methods are used to change the state of the class's members.
  • Make all the fields final and private, so that fields become non-accessible from outside the class.  Additionally, their values will not be altered because of being final.
  • The class should not be sub-classed, so make it final.  This will prevent it from being overridden.
  • There is a need to focus on mutable reference variables with a reference variable, even final cannot prevent their values to be changed. So, to prevent the reference variable's values, it's better to provide a copy of the object, instead of providing an actual object.
  • Make the default constructor of the class private and provide instances with a factory method.

Example of making a class immutable by creating a final class

In the example given below, we create a final class named Student. There is only one final data member, a constructor, and a getter method.
  1. public final class Student {  
  2.  final int RollNumber;  
  3.  public Student(int RollNumber) {  
  4.   this.RollNumber = RollNumber;  
  5.  }  
  6.  public int getRollNumber() {  
  7.   return RollNumber;  
  8.  }  
  9. }  
The class in the preceding example is an immutable class because:
  • The instance variable of the class is final, so after creating it, we cannot change its value.
  • We cannot create a sub-class, because the class is declared as final.
  • There is no setter method, so there is no chance of changing the value of the instance variable.

Another example

  2. import java.util.Date;  
  3. public final class Student {  
  4.  private int RollNumber;  
  5.  private String Name;  
  6.  private Date CurrentDate;  
  7.  private Student(int RollNumber, String Name, Date CurrentDate) {  
  8.   this.RollNumber = RollNumber;  
  9.   this.Name = Name;  
  10.   this.CurrentDate = CurrentDate;  
  11.  }  
  12.  static Student getInstance(int f1, String f2, Date f3) {  
  13.   return new Student(f1, f2, f3);  
  14.  }  
  15.  public int getRollNumber() {  
  16.   return RollNumber;  
  17.  }  
  18.  public String getName() {  
  19.   return Name;  
  20.  }  
  21.  public Date getCurrentDate() {  
  22.   return new Date(CurrentDate.getTime());  
  23.  }  
  24. }  
  26. import java.util.Date;  
  27. public class StudentImmutable {  
  28.  public static void main(String args[]) {  
  29.   Student std = Student.getInstance(101"Rakesh"new Date());  
  30.   System.out.println("RollNumber:" + std.getRollNumber() + " Name:" + std.getName() + " Date:" + std.getCurrentDate());  
  31.   std.getCurrentDate().setDate(3);  
  32.   System.out.println("RollNumber:" + std.getRollNumber() + " Name:" + std.getName() + " Date:" + std.getCurrentDate());  
  33.  }  
  34. }