Java Reference
In-Depth Information
At this point, the wrapper object holds 101 and there is no way to change it. Therefore, the IntWrapper class is an
immutable class and its objects are immutable objects. You might have noticed that two changes were made to the
IntHolder class to convert it to the IntWrapper class. The setValue() method was removed and the value instance
variable was made final . In this case, it was not necessary to make the value instance variable final . The use of the
final keyword makes your intention clear to the reader of the class and it protects the value instance variable from
being changed inadvertently. It is good practice (use it as a rule of thumb) to declare all instance variables that define the
immutable state of an object final so the Java compiler will enforce the immutability during compile time. The objects
of IntWrapper class are immutable internally as well as externally. There is no way to change its state once it is created.
Let's create a variant of the IntWrapper class, which will be externally immutable but internally mutable. Let's call
it IntWrapper2 . It is listed in Listing 7-17.
Listing 7-17. An Example of an Externally Immutable and Internally Mutable Class
// IntWrapper2.java
package com.jdojo.object;
public class IntWrapper2 {
private final int value;
private int halfValue = Integer.MAX_VALUE;
public IntWrapper2(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public int getHalfValue() {
// Compute half value if it is not already computed
if (this.halfValue == Integer.MAX_VALUE) {
// Cache the half value for future use
this.halfValue = this.value / 2;
}
return this.halfValue;
}
}
IntWrapper2 adds another instance variable called halfValue , which will hold the half value of the value that is
passed to the constructor. It is a trivial example. However, it serves the purpose to explain what you mean by externally
and internally immutable objects. Suppose (just for the sake of this discussion) that computing half of an integer is a
very costly process and you do not want to compute it in the constructor of the IntWrapper2 class, especially if nobody
every asks for it. The halfValue instance variable is initialized to the maximum integer value, which works as a flag
that it is not computed yet. You have added a getHalfValue() method, which checks if you have already computed
the half value. For the first time, it will compute the half value and cache it in halfValue instance variable. From the
second time onward, it will simply return the cached value.
The question is, “Is an IntWrapper2 object immutable?” The answer is yes and no. It is internally mutable.
However, it is externally immutable. Once it is created, its client will see the same return value from the getValue()
and getHalfValue() methods. However, its state ( halfValue to be specific) changes once in its lifetime when the
getHalfValue() method is called for the first time. However, this change is not visible to the users of the object. This
method returns the same value on all subsequent calls. Objects like IntWrapper2 are called immutable objects. Recall
that typically an immutable object means externally immutable.
 
Search WWH ::




Custom Search