An object is considered to be immutable if its value cannot change after it is created.
Example: let’s see what happens when we do something like this:
String string1 = "Hello String !"; System.out.println(string1); string1 = "Hello !"; System.out.println(string1);
If you run this example, you get:
Hello String ! Hello !
The first impression is that the string1 has changed its value from “Hello String !” to “Hello !”, but this is wrong because:
- String is immutable
- string1 is a String reference and NOT an object;
So, in reality, the second instruction generates a new String object and string1 reference gets the address of the new object, like this:
Immutable objects are particularly very useful in multi-threaded applications. Since they cannot change state, they won’t get currupted by thread interference or observed in an inconsistent state. Objects of java.lang.Integer and java.lang.String classes are the examples of immutable objects . Immutable objects can simplify your program, since they :
- are automatically thread-safe.
- are simple to use test and construct.
- don’t require a copy constructor.
- don’t require an implementation of clone.
- allow hashCode to use lazy initialization, and to cache its return value.
- do not need to be copied defensively when used as a field.
- are good Map keys and Set elements (these objects must not change state while stored in the collection).
- have their class invariant established once upon construction, and it never needs to be checked again.
- always have failure atomicity (a term used by Joshua Bloch) : if an immutable object throws an exception, it’s never left in an undesirable or indeterminate state.