Don't let this reference escape
Within a class, the 'this' Java keyword refers to the native object, the current instance of the class. The this reference should refer to a fully formed object. Within the body of a constructor, however, there is no fully formed object, even on the last line of the constructor. The object is fully-formed only after the constructor completes.
Within a constructor, you can get into trouble if you let the this reference "escape".
This is occurs mainly with listeners. Here is an example which illustrates the point.
import java.util.Observable; import java.util.Observer; public final class EscapingThisReference { /** A RadioStation is observed by the people listening to it. */ static final class RadioStation extends Observable { //elided } /** A listener which doesn't let the 'this' reference escape. 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 aPersonsName, RadioStation aStation){ //first call the private constructor GoodListener result = new GoodListener(aPersonsName); //the 'result' object is now fully constructed... aStation.addObserver(result); return result; } public void update(Observable aStation, Object aData) { //..elided } private String fPersonsName; /** Private constructor. */ private GoodListener(String aPersonsName){ fPersonsName = aPersonsName; } } /** A listener which lets an explicit 'this' reference escape before construction is completed. */ static final class BadListenerExplicit implements Observer { /** Ordinary constructor. */ BadListenerExplicit(String aPersonsName, RadioStation aStation){ fPersonsName = aPersonsName; //DANGEROUS - the 'this' reference is not valid, since the //constructor hasn't yet completed; it doesn't matter if //this is the last statement in the constructor aStation.addObserver(this); } public void update(Observable aStation, Object aData) { //..elided } private String fPersonsName; } /** Another listener that lets its 'this' reference escape before construction is completed; here, the 'this' reference is implicit, via the inner class. */ static final class BadListenerImplicit { /** Ordinary constructor. */ BadListenerImplicit(String aPersonsName, RadioStation aStation){ fPersonsName = aPersonsName; //DANGEROUS aStation.addObserver( new Observer(){ public void update(Observable aObservable, Object aData) { doSomethingUseful(); } } ); } private void doSomethingUseful() { //..elided } private String fPersonsName; } }
See Also :
Would you use this technique?
|
|