Immutable Objects
In this section, you will learn what an immutable object is, how you can achieve immutability in Java and what are the advantages and disadvantages of these objects.
In the previous section we have seen that modifying the state of an object can lead to confusing situations when we have multiple references to them.
Immutable objects are designed such that they never change their state. The values of their instance variables cannot be changed, and therefore make this type of confusion impossible.
Thus, we do not need to copy immutable objects to prevent their state from being changed, which is a large advantage of an immutable object. A String is an example of an immutable object. When concatenating two strings, we get a new String, not altering the old string objects. Other examples are the non-primitive versions of primitive types, such as Double
and Integer
.
First, we have a look at a String
example, were we have String str = "abc";
.
If we want the letter c as a String
object, we need to create a new object, or explicitly overwriting the old object, basically creating a new one and throwing the old object away.
For instance, we can state String c = str.substring(2,3);
.
The substring method returns the letter c, which is stored in the variable with the same name.
On the other hand, if we would only call str.substring(2,3);
, nothing would happen.
After both calls the first variable would still contain the string "abc"
.
If we would make the call str = str.substring(2,3);
, the variable seems to change, but behind the scenes it replaces the reference to the old string "abc"
away to store a reference to the the new string "c"
in the variable named str
.
BigInteger
Another example of an immutable object is BigInteger
which allows us to do integer calculations with numbers that are too big to fit in an int
or long
,
avoid the overflow that can occur with those types.
First, you import it: import java.math.BigInteger
. Then, take a look at this example where we use it:
// To create an instance of BigInteger,
// we use a special static method valueOf, not a constructor.
// Some classes are designed this way by their programmers.
BigInteger a = BigInteger.valueOf(233);
BigInteger addValue = Biginteger.ValueOf(144);
BigInteger b = a;
b.add(addValue);
System.out.println(a);
System.out.println(b);
What do you will be printed here?
If you want to create your own class for immutable objects, follow these simple rules:
- Do not add any setter method.
- Declare all fields final and private.
- If a field is a mutable object itself, create copies of it for getter methods.
- If a mutable object is passed as an argument to the constructor, it must be assigned to a variable to create a immutable copy of it. It may also be convenient to write additional constructors to facilitate the creation of new objects.
- Do not write mutation methods, but write methods that compute the new state and return a new instance with that state.
Lastly, we will list the advantages and disadvantages of immutable objects here.
Test your knowledge
Explain what a immutability is. Can you give an example of a commonly used Java class that is immutable? Can you also name a mutable class?
Adjust the following mutable class so that it becomes immutable:
public class Doubler {
private int number;
public Doubler(int initialValue) {
this.number = initialValue;
}
public int getNumber() {
return number;
}
public void doubleNumber() {
number *= 2;
}
}
Name an advantage and name a disadvantage of making a class immutable.