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 :
Constructors in general
Constructors shouldn't start threads
Would you use this technique?
Yes   No   Undecided   
© 2013 Hirondelle Systems | Source Code | Contact | License | RSS
Individual code snippets can be used under this BSD license - Last updated on August 30, 2012.
Over 2,400,000 unique IPs last year - Built with WEB4J.
- In Memoriam : Bill Dirani -