Arrays.copyOf在使类成为不可变的过程中扮演什么角色?

时间:2016-08-07 09:14:25

标签: java

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
    }
}

作者提到

  

OneValueCache在没有copyOf调用的情况下不会是不可变的   构造函数和getter。为方便起见,添加了Arrays.copyOf   Java 6;克隆也可以。

1)Arrays.copyOf在使上述类成为IMMUTABLE时扮演什么角色?如何?

上面的不可变类正在被这样使用 -

@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);
    }

}

1 个答案:

答案 0 :(得分:10)

如果您返回this.lastFactors而不是返回副本,则调用者可以执行(例如)

BigInteger[] lastFactors = cache.getFactors(...);
for (int i = 0; i < lastFactors.length; i++) {
    lastFactors[i] = null;
}

因此改变了缓存的状态,这应该是不可变的。

构造函数的解释类似。如果构造函数没有复制,则调用者可以执行

factors = factor(i);
cache = new OneValueCache(i, factors); 
for (int i = 0; i < lastFactors.length; i++) {
    factors[i] = null;
}

因此再次改变了缓存的状态。

经验法则:数组总是可变的(空数组除外)。因此,如果不可变类的状态包含数组,则调用者必须无法引用该数组。