satish's blog

satish's picture

Calling subclass method from base class constructor in Java

Let us start with a simple Java program:

class A{
   String str = "Hello";

   public A(){
      init();
   }

   void init(){
      System.out.println(str);
   }

   public static void main(String[] args){
      new A();
   }
}

Pretty simple code, ain't it?
This will print "Hello" to the console.
Now see this:

class A extends B{

    public static void main(String[] args) {
        new A();
    }

    String str = "Hello";

    @Override
    void init() {
        System.out.println(str);
    }

}

abstract class B{
    public B(){
        //Do some initialization
        //and run the rest of the code
        init();
    }

    abstract void init();
}

If you think this time too it prints "Hello" then I am glad I have some one who thinks like me
Well it actually prints "null"
That is because 'str' is not yet initialized! Yes

If we call a subclass method from the super class' constructor, the subclass' variables will not be initialized to the default values. I learned this the hard way. The only workaround is to set the values in the init() method or simply not use this approach at all.

I needed to run the subclass code in a separate thread with a particular Subject

Do comment if you know any better way to do this

Update: A solution is suggested here: http://benpryor.com/blog/2008/01/02/dont-call-subclass-methods-from-a-su...

In summary, instead of the super class constructor calling a method overridden by the subclass, make the subclass constructor call a method that is defined in the super class. It is shown in the code below:

class A extends B{

    public static void main(String[] args) {
        new A();
    }

    String str = "Hello";
    
    public A(){
	//Call a method in superclass to do the initialization
	//This method will call init() back
	pre_init();
    }


    @Override
    void init() {
        System.out.println(str);
    }

}

abstract class B{
    public B(){
    }

    void pre_init(){
	//Do some initialization
        //and run the rest of the code
	init();
    }

    abstract void init();
}

 

Syndicate content