Tech Master Tutorials
Email Facebook Google LinkedIn Pinterest Twitter
Home Java Java 8 Java Interview Questions Java8 Interview Questions Object Oriented Programming in Java JVM Java Programming

Immutability

What is Immutability

A class is called immutable if once object is created for that class then its state/contents can not be changed.
If you want any change in the current object that can not be done but you can create a new object with the new details.
e.g String is an immutable class. Once String object is created then it can not be changed. Any modification call on a string object results in a new string object.


Why do we need immutable objects :
  1. Security – Passing data over network using string(immutable objects) is a secure way to transmit the data as being immutable objects strings can not be modified once created.
  2. Thread safe – Since immutable objects can not be modified and can only be read by threads, so no thread safety is required.
  3. To avoid unnecessary modifications – Also in a system, if we don’t expect some object to change after creation, better to keep them immutable to avoid any unexpected modification.
  4. To have a capability like String Constant Pool – String constatnt pool is a pool string constants or String literals. To know more about String constant pool follow -the link

Writing an Immutable class

Below Employee class is an immutable class :
Object created from the below class can not be modified once created.

Steps to be followed make a class immutable :
  1. Make class final – To stop from being extended
  2. Have private and final fields : To stop from being modification from outside or within class
  3. Initialization through constructor while creation
  4. Have no setter methods
  5. Getter should provide only deep copy of the objects to outside, to stop modification outside of the class
Below class is an example of immutable class: Student – name, rollno, list courses
public final class Employee {

	private final int id;
	private final String name;
	
	public Employee(int id, String name){
		this.id = id;
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public String getName() {
		return name;
	}
	
}
In the above class, we have not provided any setter method.
Also we have only primitive variables and when we get the values of the primitive variables then a copy of the values is provided to the calling method.
Hence from outside these values can not be updated.

Lets take another example of the below Student class :
package immutability;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public final class Student {
	private final int rollNumber;
	private final String name;
	private final List<String> subjects;

	public Student(int rollNumber, String name, List<String> subjects) {
		this.rollNumber = rollNumber;
		this.name = name;
		this.subjects = subjects;
	}

	public int getRollNumber() {
		// here we are returning value, outside the class value of this int
		// variable cannot be changed
		return rollNumber;
	}

	public String getName() {
		// String is immutable, even if we return object cannot be changed
		return name;
	}

	public List<String> getSubjects() {
		// here we are returning a deep copy of the object.
		// So even if outside of this class, returned object is changed even
		// then subjects list will not be affected.
		return subjects.stream().collect(Collectors.toList());
	}

	public static void main(String[] args) {
		List<String> subjects = new ArrayList<String>();
		subjects.add("maths");
		subjects.add("science");
		subjects.add("computers");

		int rollNumber = 1;
		String name = "John";

		// creating immutable object - stident
		Student studentImmutable = new Student(rollNumber, name, subjects);

		String nameFromImmutableObj = studentImmutable.getName();
		int rollNumberFromImmutableObj = studentImmutable.getRollNumber();
		List<String> subjectsListFromImmutableObj = studentImmutable.getSubjects();

		System.out.println("name from the immutable class before update : name = " 
																+ nameFromImmutableObj);
		System.out.println("rollNumber from the immutable class before update : rollNumber = " 
																		+ rollNumberFromImmutableObj);
		System.out.println("Subjects from the immutable class before update : subjects = " 
																		+ subjectsListFromImmutableObj);

		// then update
		nameFromImmutableObj = "test";
		rollNumberFromImmutableObj = 2;
		subjectsListFromImmutableObj.add("newSubject");

		// then get and print again
		String nameFromImmutableObj_1 = studentImmutable.getName();
		int rollNumberFromImmutableObj_1 = studentImmutable.getRollNumber();
		List<String> subjectsListFromImmutableObj_1 = studentImmutable.getSubjects();

		System.out.println();
		System.out.println();
		System.out.println("name from the immutable class after update : name = " 
																	+ nameFromImmutableObj_1);
		System.out.println("rollNumber from the immutable class after update : rollNumber = " 
																	+ rollNumberFromImmutableObj_1);
		System.out.println("Subjects from the immutable class after update : subjects = " 
																	+ subjectsListFromImmutableObj_1);
	}

}