Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a Java example of the "private constructor capture" idiom?

Tags:

java

Can some one explain to me the private constructor capture idiom with an example and point out where we actually need / do not need this kind of design?

like image 213
Inquisitive Avatar asked Jul 06 '12 10:07

Inquisitive


Video Answer


2 Answers

The aim is to capture a temporary value during construction.

An example is given in Solution 53 of Java Puzzlers:

public class MyThing extends Thing {
    private final int arg;

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

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

In this case, we want to capture and store the parameter that we wish to pass to the superclass constructor. In order to do so, we create a private helper constructor, which our public constructor then calls.

like image 118
Oliver Charlesworth Avatar answered Oct 04 '22 11:10

Oliver Charlesworth


An explanation is given with an example in Java Concurrency In Practice chapter 4 section 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;
    }
}

The private constructor exists to avoid the race condition that would occur if the copy constructor were implemented as this(p.x, p.y).

What does it mean is, if you did not have a private constructor and you implement copy constructor in following way:

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

Now assume that thread A is having the access to SafePoint p is executing above copy constructor's this(p.x, p.y) instruction and at the unlucky timing another thread B also having access to SafePoint p executes setter set(int x, int y) on object p. Since your copy constructor is accessing p's x and y instance variable directly without proper locking it could see inconsistent state of object p.

Where as the private constructor is accessing p's variables x and y through getter which is synchronized so you are guaranteed to see consistent state of object p.

like image 21
MNA Avatar answered Oct 04 '22 12:10

MNA