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 :
- 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.
- Thread safe – Since immutable objects can not be modified and can only be read by threads, so no thread safety is required.
- 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.
- 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 :
- Make class final – To stop from being extended
- Have private and final fields : To stop from being modification from outside or within class
- Initialization through constructor while creation
- Have no setter methods
- Getter should provide only deep copy of the objects to outside, to stop modification outside of the class
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); } }