Introduction

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

  1. Student.java
  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. }
  25. StudentImmutable.java
  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. }

Output

Output