Calling subclass method from base class constructor in Java

satish's picture

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();
}

 

Comments

saifikhan's picture

What is the '@override'

What is the '@override' before init() in class A ?

Object construction semantics in C++ start involve walking up the inheritance tree and any access to the derived class from a 'ancestor' class will lead to the slicing problem. i suspect that Java mirrors the same semantics.

Further to avoid stack unwinding issues, it may be a good idea to create objects via mixin/template model. ATL does it very elegantly.

Saifi.

satish's picture

@override is an annotation

@override is an annotation that informs the compiler that this method overrides a base class method. This is optional, but the compiler will raise an error if we fail to override properly

Anonymous's picture

Sir, Please find the code

Sir, Please find the code below to understand your problem . Java automatically inserts calls to the base-class constructor in the derived-class constructor. The following example shows this working with three levels of inheritance: /: Cartoon.java // Constructor calls during inheritance class Art { Art() { System.out.println("Art constructor"); } } class Drawing extends Art { Drawing() { System.out.println("Drawing constructor"); } } public class Cartoon extends Drawing { Cartoon() { System.out.println("Cartoon constructor"); } public static void main(String[] args) { Cartoon x = new Cartoon(); } } ///:~ The output for this program shows the automatic calls: Art constructor Drawing constructor Cartoon constructor You can see that the construction happens from the base “outward,” so the base class is initialized before the derived-class constructors can access it. NOW U THINK WHY UR GETTING NULL FIRST TIME !!!!

Post new comment

CAPTCHA
Thank you for using Captcha to prevent automated spam submissions.
2 + 1 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.