In this tutorial, we are going to see how to create immutable class in java.
Immutable class is class whose state can not be changed once created.
Example: String is best example for immutable class. Once you create a String, you can not change it.
Immutable class is very simple to understand, it has only one state. Immutable class is carefully instantiated by the constructor. Immutable classes are thread safe. This is biggest advantage of immutable class, you don’t need to apply synchronization for immutable objects. Immutable class can be useful while putting object of immutable class in HashMap or it can be used for caching purpose because its value won’t change.
Immutable objects are by default thread safe.
Steps for creating a immutable class:
- Make your class final :Â
If you make your class final, no class will be able to extend it, hence will not be able override methods of this class. - Declare all instance variable with private and final :Â
If you make instance variable private, no outside class will be able to access instance variables and if you make them final, you can not change it. - Say no to setter methods :
Don’t create setter method for any instance variables, hence there will be no explicit way to change state of instance variables. - Initialize all variables in constructor :
You can initialize variables in constructor. You need to take special care while working with mutable object. You need to do deep copy in case of imutable objects. - Perform cloning of mutable objects while returning from getter method:
If you return clone of object from getter method, it won’t return original object, so your original object will remain intact. I will explain this more in later part of this tutorial.
Read : Why String is immutable in java
Lets understand immutable class with a very simple example:
Lets create a simple class called Country.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public final class Country{ private final String countryName; private final ArrayList listOfStates; public Country(String countryName,ArrayList listOfStates) { super(); this.countryName = countryName; this.listOfStates=listOfStates; } public String getCountryName() { return countryName; } public ArrayList getListOfStates() { return listOfStates; } public static void main(String args[]) { ArrayList listOfStates=new ArrayList(); listOfStates.add("Madhya Pradesh"); listOfStates.add("Maharastra"); listOfStates.add("Gujrat"); Country country=new Country("India",listOfStates); System.out.println("Country : "+country.getCountryName()); System.out.println("List of states : "+country.getListOfStates()); // It will be added to the list because we did not use clone in getListOfStates country.getListOfStates().add("Kerala"); // It will be added to the list because we did not use deep copy in constructor listOfStates.add("Rajasthan"); System.out.println("Updated List of states : "+country.getListOfStates()); } } |
When you run the program, you will get below output:
1 2 3 4 5 |
Country : India List of states : [Madhya Pradesh, Maharastra, Gujrat] Updated List of states : [Madhya Pradesh, Maharastra, Gujrat, Kerala, Rajasthan] |
Above class is not immutable. There are two reasons for it :
- We did not use clone in getListOfStates() method, so we are able to add “Kerala” to the listOfStates.
- We did not do deep copy for listOfStates , so we are able to add “Rajasthan” to the list.
Lets use clone in getListOfStates() method and see the difference, just change getListOfStates() to below code:
1 2 3 4 5 |
public ArrayList getListOfStates() { return (ArrayList) listOfStates.clone(); } |
1 2 3 4 5 |
Country : India List of states : [Madhya Pradesh, Maharastra, Gujrat] Updated List of states : [Madhya Pradesh, Maharastra, Gujrat, Rajasthan] |
We are one step closed to immutable class now.Â
Lets change constructor to make deep copy of listOfStates object.
1 2 3 4 5 6 7 8 9 10 11 12 |
public Country(String countryName, ArrayList listOfStates) { super(); this.countryName = countryName; ArrayList tempList = new ArrayList(); for (int i = 0; i < listOfStates.size(); i++) { tempList.add(listOfStates.get(i)); } this.listOfStates = tempList; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
package org.arpit.java2blog.bean; import java.util.ArrayList; public final class Country { // declared private final instance variable private final String countryName; // Mutable object private final ArrayList listOfStates; public Country(String countryName, ArrayList listOfStates) { super(); this.countryName = countryName; // Creating deep copy for mutable object ArrayList tempList = new ArrayList(); for (int i = 0; i < listOfStates.size(); i++) { tempList.add(listOfStates.get(i)); } this.listOfStates = tempList; } public String getCountryName() { // Do not need to do cloning as it is immutable object return countryName; } public ArrayList getListOfStates() { // Returning cloned object return (ArrayList) listOfStates.clone(); } public static void main(String args[]) { ArrayList listOfStates = new ArrayList(); listOfStates.add("Madhya Pradesh"); listOfStates.add("Maharastra"); listOfStates.add("Gujrat"); String countryName="India"; Country country = new Country(countryName, listOfStates); System.out.println("Country : " + country.getCountryName()); // Lets try to change local variable countryName countryName="China"; System.out.println("Updated Country : " + country.getCountryName()); System.out.println("List of states : " + country.getListOfStates()); // It will not be added to the list because we are using clone in // getListOfStates country.getListOfStates().add("Kerala"); // It will not be added to the list because we are using deep copy in // constructor listOfStates.add("Rajasthan"); System.out.println("Updated List of states : " + country.getListOfStates()); } } |
1 2 3 4 5 6 |
Country : India Updated Country : India List of states : [Madhya Pradesh, Maharastra, Gujrat] Updated List of states : [Madhya Pradesh, Maharastra, Gujrat] |
I hope it will help you to create immutable class in java.
Was this post helpful?
Let us know if this post was helpful. Feedbacks are monitored on daily basis. Please do provide feedback as that\'s the only way to improve.