在以下代码中(从Java Concurrency in Practice第2章第2.5节, list 2.8复制):

@ThreadSafe
public class CachedFactorizer implements Servlet {
    @GuardedBy("this") private BigInteger lastNumber;
    @GuardedBy("this") private BigInteger[] lastFactors;
    @GuardedBy("this") private long hits;
    @GuardedBy("this") private long cacheHits;

    public synchronized long getHits() { return hits; }

    public synchronized double getCacheHitRatio() {
        return (double) cacheHits / (double) hits;
    }

    public void service(ServletRequest req, ServletResponse resp) {
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = null;
        synchronized (this) {
            ++hits;
            if (i.equals(lastNumber)) {
                ++cacheHits;
                factors = lastFactors.clone(); // questionable line here
            }
        }
        if (factors == null) {
            factors = factor(i);
            synchronized (this) {
                lastNumber = i;
                lastFactors = factors.clone(); // and here
            }
        }
        encodeIntoResponse(resp, factors);
    }
}

为什么克隆factorslastFactors数组?不能简单地写成factors = lastFactors;lastFactors = factors;吗?只是因为factors是局部变量,然后将其传递给encodeIntoResponse,可以对其进行修改吗?

希望问题清楚。谢谢。

最佳答案

这称为防御性复制。数组是对象,因此

 factors = lastFactors

会将lastFactos的引用赋给因子,反之亦然。因此,任何人都可以在您的控制范围之外覆盖您的状态。举个例子:
private void filterAndRemove(BigInteger[] arr);
private void encodeIntoResponse(..., BigInteger[] factors) {
   filterAndRemove(factors);
}

使用我们的理论分配,filterAndRemove也将影响原始的lastFactorials。

07-26 04:29