The
advantage of immutability comes with concurrency. It is difficult to maintain
correctness in mutable objects, as multiple threads could be trying to change
the state of the same object, leading to some threads seeing a different state
of the same object, depending on the timing of the reads and writes to the said
object.

By
having an immutable object, one can ensure that all threads that are looking at
the object will be seeing the same state, as the state of an immutable object
will not change.

Rules
to define immutable classes:

The
following rules define a simple strategy for creating immutable objects.

Make all fields final and private.Don't allow subclasses to override methods.
The simplest way to do this is to declare the class as final. A more
sophisticated approach is to make the constructor private and construct
instances in factory methods.

If the instance fields include references
to mutable objects, don't allow those objects to be changed

Don't provide methods that modify the
mutable objects.

Don't share references to the mutable
objects. Never store references to external, mutable objects passed to the
constructor; if necessary, create copies, and store references to the copies.
Similarly, create copies of your internal mutable objects when necessary to
avoid returning the originals in your methods.

Immutable
Objects:

An
immutable object is an object whose state cannot be changed. An immutable class
is a class whose instances are immutable by design, and implementation. The
Java class which is most commonly presented as an example of immutability is java.lang.String.

Some
basic types and classes in Java are fundamentally mutable. For example, all
array types are mutable, and so are classes like java.util.Data. This can be
awkward in situations where an immutable type is mandated. One way to deal with
this is to create an immutable wrapper for the mutable type. Here is a simple
wrapper for an array of integers

Example:

public class ImmutableIntArray

{

private final int[] array;

public ImmutableIntArray(int[] array)

{

this.array = array.clone();

}

public int[] getValue()

{

return this.clone();

}

}

This
class works by using defensive copying to isolate the mutable state (the
int[]) from any code that might mutate it:

The constructor uses clone() to create a
distinct copy of the parameter array. If the caller of the constructor subsequent
changed the parameter array, it would not affect the state of the ImmutableIntArray.

The getValue() method also uses clone() to
create the array that is returned. If the caller were to change the result
array, it would not affect the state of the ImmutableIntArray.

We
could also add methods to ImmutableIntArray to perform read-only operations on
the wrapped array; e.g. get its length, get the value at a particular index,
and so on.

Note
that an immutable wrapper type implemented this way is not type compatible with
the original type. You cannot simply substitute the former for the latter.

Points
to consider to create Immutable Object:

All properties must be set in the
constructor(s) or factory method(s).There should be no setters.

If it is necessary to include setters for
interface compatibility reasons, they should either do nothing or throw an
exception.

All properties should be declared as private
and final.

For all properties that are references to
mutable types:

the property should be initialized with a
deep copy of the value passed via the constructor

the property's getter should return a deep
copy of the property value.

The class should be declared as final to
prevent someone creating a mutable subclass of an immutable class.

A couple of other things to note:

Immutability does not prevent object from being
nullable; e.g. null can be assigned to a String variable.

If an immutable classes properties are
declared as final, instances are inherently thread-safe. This makes immutable
classes a good building block for implementing multi-threaded applications.