【问题标题】:What is a Java example of the "private constructor capture" idiom?什么是“私有构造函数捕获”习语的 Java 示例?
【发布时间】:2012-07-06 10:39:47
【问题描述】:

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

【问题讨论】:

    标签: java


    【解决方案1】:

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

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

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

    【讨论】:

    • 在构造函数运行但尚未完成执行时捕获对象的状态是否是个好主意?我的意思是对象可能处于不一致的状态?
    • @Subhra:我不确定你在问什么。哪个对象可能处于不一致状态?
    • 正在构建的对象本身?对象不是只有在正确构造后才处于一致状态吗?
    • @Subhra:确实。但为什么在这种情况下这很重要?我们所做的只是构造函数链接。
    • 我想这没关系,因为 arg 是最终的和私有的?
    【解决方案2】:

    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(p.x, p.y) 时会发生的竞争条件。

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2019-10-16
      • 2014-08-28
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多