-2

class Base:

public class Base {
    private String name = "base";

    public Base() {
        tellName();
        printName(name);
    }

    public void tellName() {
        System.out.println("Base tell name:" + name);
    }

    public void printName(String name) {
        System.out.println("Base print name:" + name);
    }
}

class Derived:

public class Derived extends Base {
    private String name = "Derived";

    public Derived() {
        tellName();
        printName(name);
    }

    public void tellName() {
        System.out.println("Derived tell name:" + name);
    }

    public void printName(String name) {
        System.out.println("Derived print name:" + name);
    }

    public static void main(String[] args) {
        Derived derived = new Derived();
    }
}

Result:

Derived tell name:null
Derived print name:base
Derived tell name:Derived
Derived print name:Derived

Recently, I was asked this question. I thought about it, but didn't have exact answer of why this program section has such execute result. Hope someone can help me analyze such problem. Thanks a lot! ^-^

I just want to know the execution process of constructor in derived condition.

2 Answers2

2

There shouldn't be any confusion at all. Whenever you call the constructor, it will invoke the parent class constructor. so, when you construct Derived instance, it will implicitly call Base class constructor. This will set the member variable 'name' to value 'base' in base instance. After that the methods tellName() and printName() are invoked in the base constructor, this will actually invoke the methods on the actual instance. i.e. Derived instance. At this point, the member variable 'name' in Derived instance is null, that's why you see Derived tell name:null. After that, when the method printName is invoked by passing the 'name' member variable in base instance, this is just passed to the method in Derived instance.that's why Derived print name:base. Once the parent constructor is completed, the member variable 'name' in Derived instance is set to value 'Derived' and then it invokes the tellName() and printName(name) on the Derived instance. so, that's why we see the next two lines of output

Derived tell name:Derived
Derived print name:Derived

That's tha long story behind!

Keerthivasan
  • 12,760
  • 2
  • 32
  • 53
  • Except that it's not a StackOverflow thing to ask for upticks/acceptance. You actually risk getting downticked. – Hot Licks Oct 14 '13 at 15:45
  • 2
    (And it should be pointed out that you should not depend on the order of instance initializations. Some are performed out of the constant table and occur early, others are melded into the constructor and occur later -- it's up to the compiler and the particular data type.) – Hot Licks Oct 14 '13 at 15:47
  • Thank you very much, Keerthi Ramanathan,I was just wondering the sentence you write, such as "this will actually invoke the methods on the actual instance. i.e. Derived instance.".What was trouble me is that how does dynamic dispatch in constructor of superclass works.Does reference of Derived Class transfer to superclass?Looking for your reply,Thank you.^-^ – user2879385 Oct 14 '13 at 16:08
  • @HotLicks Thanks for the information about constant table. +1 – Keerthivasan Oct 14 '13 at 17:16
0

Execution starts in Derived.main. This creates a new instance of Derived, so the Derived constructor is invoked. This starts by invoking the Base constructor, which initialises the Base sub-object's name and then makes a call to tellName. Due to dynamic dispatch, the tellName that is called is Derived.tellName and not Base.tellName. The text this prints refers to the Derived sub-object's name, which has not yet been initialised, rather than the Base sub-object's name, which has been initialised, hence "Derived tell name:null" is printed. Control resumes in the Base constructor, which next calls printName with the Base sub-object's name. Due to dynamic dispatch, Derived.printName is invoked. The name it prints is its argument, which (as we just saw) is the name from the Base sub-object. Hence it prints "Derived print name:base", since the Base sub-object's name has previously been initialised to "base". The Base constructor has now completed, and control resumes in the Derived constructor. This now initialises the Derived sub-object's name to "Derived" and then calls Derived.tellName and Derived.printName in the obvious way, with the observed results.

As an extra observation, it's worth noting that the issue here arises because Java dynamically dispatches virtual calls in constructors; other languages such as C++ don't, e.g. see:

http://www.parashift.com/c++-faq-lite/calling-virtuals-from-ctors.html

Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80