Be Careful With Initializers in Constructors

Be Careful With Initializers in Constructors

You should use caution when automatically initializing class variables. In this example, C1 calls setVal() in its constructor, and C2, a subclass of C1, overrides the method to set a value of a C2 variable:

 public class C1{  public C1()  {    setVal();  }  protected void setVal()  {  }}public class C2  extends C1{  protected int nVal = 1;  public C2()  {    super();    System.err.println("C2 constructor: nVal=" + nVal);  }  protected void setVal()  {    int nOldVal = nVal;    nVal = 2;    System.err.println("C2.setval: nOldVal=" + nOldVal + ", nVal=" + nVal);  }  public static void main(String[] args)  {    C2 c2 = new C2();    System.err.println("C2.main: nVal=" + c2.nVal);  }}

When C2 is instantiated, this code appears on the console:

 C2.setval: nOldVal=0, nVal=2C2 constructor: nVal=1C2.main: nVal=1

Note that when all is done, nVal equals 1, not 2 because the initial values for C2’s variables aren’t set until the base class constructor has completed its work. As a result, C2’s constructor calls C1’s constructor, which invokes setVal; setVal sets the C2 variable nVal. Note that the value setVal() sees for nVal is 0, not 1. C1’s constructor returns, and the construction of C2 continues. C2 variables that are given explicit values are then initialized, which wipes out what setVal just did.

This problem does not occur for variables that don’t have explicit initializers. Therefore, be careful in designing methods in a base class constructor that can be overridden in subclasses. If the subclass has variables that are initialized when they are declared, the overridden methods should not use those variables at all.


Share the Post: