An extract/ snippet from Java Concurrency in Practice-
@Immutable
class OneValueCache{
private final BigInteger lastNumber;
private final BigInteger[] lastFactors;
public OneValueCache(BigInteger i, BigInteger[] factors) {
this.lastNumber = i;
this.lastFactors = Arrays.copyOf(factors,factors.length); // 1
}
public BigInteger[] getFactors(BigInteger i){
if(lastNumber == null || lastNumber.equals(i))
return null;
else
return Arrays.copyOf(lastFactors,lastFactors.length); // 2
}
}
The author mentions
OneValueCache wouldn't be immutable without the copyOf calls in the constructor and getter. Arrays.copyOf was added as a convenience in Java 6; clone would also work.
1) What role does Arrays.copyOf plays in making the above class as IMMUTABLE? How?
The above immutable class is being utilised like this-
@ThreadSafe
public class VolatileCachedFactorizer implements Servlet{
private volatile OneValueCache cache = new OneValueCache(null, null);
public void service(ServletRequest req, ServletResponse resp){
BigInteger i = extractFromRequest(req);
BigInteger[] factors = cache.getFactors(i);
if(factors == null){
factors = factor(i);
cache = new OneValueCache(i, factors); // cache being volatile, hence @ThreadSafe
}
encodeIntoResponse(resp, factors);
}
}
If you return this.lastFactors
instead of returning a copy, the caller can do (for example)
BigInteger[] lastFactors = cache.getFactors(...);
for (int i = 0; i < lastFactors.length; i++) {
lastFactors[i] = null;
}
and thus mutate the state of the cache, which is supposed to be immutable.
The explanation is similar for the constructor. If the constructor didn't make a copy, the caller could do
factors = factor(i);
cache = new OneValueCache(i, factors);
for (int i = 0; i < lastFactors.length; i++) {
factors[i] = null;
}
and thus once again mutate the state of the cache.
Rule of thumb: an array is always mutable (except the empty array). So, if the state of an immutable class contains an array, then the caller must not be able to have a reference to the array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With