How to make a class immutable?

Technology: java
AskedIn:
Topics:
Type:
  • Declare a class final so it can’t be extended further
  • Make all the fields private so that there is no direct way to access them
  • Don’t provide setter methods for fields
  • Make all the fields final so that they be initialized only once
  • Initialize all the fields with help of constructor method performing deep copy
  • Preform cloning of objects in getter methods to return a copy rather than returning the actual object reference

Example

import java.util.HashMap;

import java.util.Iterator;

 

public final class FinalClassExample {

 

// fields of the FinalClassExample class

private final int id;

 

private final String name;

 

private final HashMap<String,String> testMap;

 

 

public int getId() {

 return id;

}

 

public String getName() {

 return name;

}

 

// Getter function for mutable objects

 

public HashMap<String, String> getTestMap() {

 return (HashMap<String, String>) testMap.clone();

}

 

// Constructor method performing deep copy

 

public FinalClassExample(int i, String n, HashMap<String,String> hm){

 System.out.println("Performing Deep Copy for Object initialization");

 

 // "this" keyword refers to the current object

 this.id=i;

 this.name=n;

 

 HashMap<String,String> tempMap=new HashMap<String,String>();

 String key;

 Iterator<String> it = hm.keySet().iterator();

 while(it.hasNext()){

  key=it.next();

  tempMap.put(key, hm.get(key));

 }

 this.testMap=tempMap;

}

 

// Test the immutable class

 

public static void main(String[] args) {

 HashMap<String, String> h1 = new HashMap<String,String>();

 h1.put("1", "first");

 h1.put("2", "second");

 

 String s = "original";

 

 int i=10;

 

 FinalClassExample ce = new FinalClassExample(i,s,h1);

 

 // print the ce values

 System.out.println("ce id: "+ce.getId());

 System.out.println("ce name: "+ce.getName());

 System.out.println("ce testMap: "+ce.getTestMap());

 // change the local variable values

 i=20;

 s="modified";

 h1.put("3", "third");

 // print the values again

 System.out.println("ce id after local variable change: "+ce.getId());

 System.out.println("ce name after local variable change: "+ce.getName());

 System.out.println("ce testMap after local variable change: "+ce.getTestMap());

 

 HashMap<String, String> hmTest = ce.getTestMap();

 hmTest.put("4", "new");

 

 System.out.println("ce testMap after changing variable from getter methods: "+ce.getTestMap());

 

}

 

}

 

Output:

Performing Deep Copy for Object initialization

ce id: 10

ce name: original

ce testMap: {1=first, 2=second}

ce id after local variable change: 10

ce name after local variable change: original

ce testMap after local variable change: {1=first, 2=second}

ce testMap after changing variable from getter methods: {1=first, 2=second}

 

Ref: https://www.digitalocean.com/community/tutorials/how-to-create-immutable-class-in-java