9

有人可以通过示例向我解释私有构造函数捕获习语并指出我们实际需要/不需要这种设计的地方吗?

4

2 回答 2

12

目的是在施工期间获取临时价值。

Java Puzzlers的解决方案 53 中给出了一个示例:

public class MyThing extends Thing {
    private final int arg;

    public MyThing() {
        this(SomeOtherClass.func());
    }

    private MyThing(int i) {
        super(i);
        arg = i;
   }
}

在这种情况下,我们想要捕获并存储我们希望传递给超类构造函数的参数。为此,我们创建了一个私有辅助构造函数,然后我们的公共构造函数调用它。

于 2012-07-06T10:45:59.103 回答
5

Java Concurrency In Practice第 4 章 4.3.5 节给出了一个示例。

public class SafePoint {
    private int x, y;

    private SafePoint(int[] a) {
        this(a[0], a[1]);
    }

    public SafePoint(SafePoint p) {
        this(p.get());
    }

    public SafePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public synchronized int[] get() {
        return new int[] { x, y };
    }

    public synchronized void set(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

私有构造函数的存在是为了避免如果复制构造函数被实现为 this(px, py) 会发生的竞争条件。

这意味着,如果您没有私有构造函数并且您通过以下方式实现复制构造函数:

public SafePoint(SafePoint p) {
    this(p.x, p.y);
}

现在假设线程 A 可以访问 SafePoint p正在复制构造函数的 this(px, py) 指令之上执行,并且在不幸的时间另一个线程 B 也可以访问 SafePoint p在对象上执行 setter set(int x, int y)。由于您的复制构造函数在没有适当锁定的情况下直接访问pxy实例变量,因此它可能会看到对象p的不一致状态。

由于私有构造函数通过同步的 getter 访问p的变量xy,因此您可以保证看到对象p的一致状态。

于 2017-10-03T15:33:11.503 回答