什么是"私有构造函数捕获"习惯用法的Java示例?

Inq*_*ive 9 java

有人可以用一个例子向我解释私有构造函数捕获习惯用法并指出我们实际需要/不需要这种设计的地方吗?

Oli*_*rth 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;
   }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们希望捕获并存储我们希望传递给超类构造函数的参数.为了做到这一点,我们创建了一个私有帮助器构造函数,然后我们的公共构造函数调用它.


小智 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

public SafePoint(SafePoint p) {
    this(p.x, p.y);
}
Run Code Online (Sandbox Code Playgroud)

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

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