Constructors in general
Constructors shouldn't start threads
'this'
Java keyword refers to the native object, the
current instance of the class.
Within a constructor, you can use the this
keyword in 3 different ways:
this(...);
this.fName
blah.operation(this);
You can get into trouble with the last form.
The problem is that, inside a constructor, the object is not yet fully constructed.
An object is only fully constructed after its constructor completely returns, and not before.
But when passed as a parameter to a method of some other object, the this
reference
should always refer to a fully-formed object.
This problem occurs mainly with listeners.
Here's an example which illustrates the point:
import java.util.Observable; import java.util.Observer; /** @author javapractices.com @author Andrew Sackett */ public final class EscapingThisReference { /** A RadioStation is observed by the people listening to it. */ static final class RadioStation extends Observable { //elided } /** A listener which waits until this object is fully-formed before it lets it be referenced by the outside world. Uses a private constructor to first build the object, and then configures the fully-formed object as a listener. */ static final class GoodListener implements Observer { /** Factory method. */ static GoodListener buildListener(String personsName, RadioStation station){ //first call the private constructor GoodListener result = new GoodListener(personsName); //the 'result' object is now fully constructed, and can now be //passed safely to the outside world station.addObserver(result); return result; } @Override public void update(Observable station, Object data) { //..elided } private String personsName; /** Private constructor. */ private GoodListener(String personsName){ this.personsName = personsName; //ok } } /** A listener which incorrectly passes a 'this' reference to the outside world before construction is completed. */ static final class BadListenerExplicit implements Observer { /** Ordinary constructor. */ BadListenerExplicit(String personsName, RadioStation station){ this.personsName = personsName; //OK //DANGEROUS - the 'this' reference shouldn't be passed to the listener, //since the constructor hasn't yet completed; it doesn't matter if //this is the last statement in the constructor! station.addObserver(this); } @Override public void update(Observable station, Object data) { //..elided } private String personsName; } /** Another listener that passes out a 'this' reference to the outside world before construction is completed; here, the 'this' reference is implicit, via the anonymous inner class. */ static final class BadListenerImplicit { /** Ordinary constructor. */ BadListenerImplicit(String personsName, RadioStation station){ this.personsName = personsName; //OK //DANGEROUS station.addObserver( new Observer(){ @Override public void update(Observable observable, Object data) { doSomethingUseful(); } } ); } private void doSomethingUseful() { //..elided } private String personsName; } }