Immutable Objects

What is Immutable Object
An immutable object is something whose state can't be change after there creation, e.g. String objects. Once you have created a String object, you can't alter this.

Creating an Immutable object's class
Creating an immutable object's class can be tricky. Minimal requirement to create an immutable object's class is, make class and every member variable, "final".

public final class SimpleImmutableClass {
 final int intVal = 5;
 final String sampleString = "Hello";
 final Integer intObj = Integer.valueOf(10);
}

SimpleImmutableClass is a class of mutable object, one can't change its state, once object is created. But it is too simple case. In real world situation is far more complex, you will rarely find such a simple class that has only primitive or immutable members (actually String and Integer classes are classes for immutable objects, provided by JDK API stack).

Consider following example, that has mutable objects as members, though every member is final, private and has only getters (to access) and no setters, but still do you think that it is a class that can produce immutable objects.
public final class NotAnImmutableClass{
private final ArrayList<String> sampleList = new ArrayList<String>();
 private final Date today = new Date();
 
 public ArrayList<String> getSampleList() {
  return sampleList;
 }
 public Date getToday() {
  return today;
 }
}

What do you think about above class, is it really an Immutable object's class? Unfortunately, a big NO. At first it seems like it is an immutable object's class, after all, it is a final class, every variable is final and private and to give more assurance, it doesn't contain any "setter" method. Some may give me a good fight arguing about immutability of the objects of this class.
But then comes the villain, the very basic of Java, the "Reference".  Consider the following listing:

class PokeIntoSoCalledImmutableClass {
public void poke(){
  NotAnImmutableClass notAnImmutableClass = new NotAnImmutableClass();
  List<String> samples = notAnImmutableClass.getSampleList();
  Date d = notAnImmutableClass.getToday();
  samples.add("Poked String");
  d.setYear(111);  
  System.out.println(notAnImmutableClass.getSampleList().size());
  System.out.println(notAnImmutableClass.getToday());
 }
 
}
What do you think, the method  poke() would print? Do you think it would print "0" and "Sun Jun 05 00:00:00 IST 2010"?  Answer is a big NO!!!

So, here comes another rule for a class whose objects to be immutable, either it should not have any mutable field (as in our case) or it should not publish (expose) its mutable members.

But again question is, what if we have to expose mutable objects and still we need that our class's objects are immutable? Well answer is simple but tricky. USE CLONING!!!! If exposed object contains only immutable objects or primitive types, use shallow copy, otherwise use deep copy.
Correct way to implement Immutable class:

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class AnImmutableClass {
 private final ArrayList<String> sampleList = new ArrayList<String>();
 private final Date today = new Date(110,5,5);
 
 public ArrayList<String> getSampleList() {
  ArrayList<String> returnList = new ArrayList<String>();
  for(String s : sampleList){   
   returnList.add(s);
  }
  return returnList;
 }
 public Date getToday() {
  return (Date)today.clone();
 }
 
 public static void main(String[] args) {
  PokeIntoSoCalledImmutableClass pokeClass = new PokeIntoSoCalledImmutableClass();
  pokeClass.poke();
 }
 
}

class PokeIntoSoCalledImmutableClass {
 public void poke(){
  AnImmutableClass anImmutableClass = new AnImmutableClass();
  List<String> samples = anImmutableClass.getSampleList();
  Date d = anImmutableClass.getToday();
  samples.add("Poked String");
  d.setYear(111);  
  System.out.println(anImmutableClass.getSampleList().size());
  System.out.println(anImmutableClass.getToday());
 }
 
}

I here conclude with set of rules to make a class whose objects are immutable:
  • Must be final
  • Only final members should be exposed to outer world
  • Exposed members should be immutable
  • If it is require to expose mutable members, then use shallow or deep cloning while exposing them