有人可以用一个例子向我解释私有构造函数捕获习惯用法,并指出我们实际需要/不需要这种设计的地方吗?
答案 0 :(得分: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;
}
}
在这种情况下,我们希望捕获并存储我们希望传递给超类构造函数的参数。为了做到这一点,我们创建了一个私有帮助器构造函数,然后我们的公共构造函数调用它。
答案 1 :(得分:1)
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;
}
}
私有构造函数的存在是为了避免在复制构造函数实现为此时发生的竞争条件(p.x,p.y)。
这意味着,如果您没有私有构造函数并且您以下列方式实现了复制构造函数:
public SafePoint(SafePoint p) {
this(p.x, p.y);
}
现在假设线程A可以访问SafePoint p 正在复制构造函数的上面执行此(px,py)指令,并且在不幸的时机,另一个线程B也可以访问SafePoint p 在对象 p 上执行setter set(int x,int y)。由于您的复制构造函数直接访问 p 的 x 和 y 实例变量而没有正确锁定,因此可能会看到对象的不一致状态<强> p 强>
私人构造函数通过同步的getter访问 p 的变量 x 和 y ,以确保您获得保证查看对象的一致状态 p 。