java构造函数在基类和派生类之间执行的过程

时间:2013-10-14 15:19:40

标签: java

类别基础:

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

类派生:

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

结果:

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

最近,我被问到这个问题。我想到了,但没有确切的答案为什么这个程序部分有这样的执行结果。 希望有人能帮我分析这样的问题。非常感谢! ^ - ^

我只想知道派生条件下构造函数的执行过程。

2 个答案:

答案 0 :(得分:2)

根本不应该有任何混淆。无论何时调用构造函数,它都将调用父类构造函数。因此,当您构造Derived实例时,它将隐式调用Base类构造函数。这会将成员变量'name'设置为基本实例中的值'base'。之后,在基础构造函数中调用方法tellName()printName(),这实际上将调用实际实例上的方法。即派生实例。此时,Derived实例中的成员变量“name”为null,这就是您看到Derived tell name:null的原因。之后,当通过在基本实例中传递'name'成员变量来调用方法printName时,这只是传递给Derived实例中的方法。这就是Derived print name:base的原因。完成父构造函数后,Derived实例中的成员变量'name'将设置为值'Derived',然后它将在Derived实例上调用tellName()和printName(name)。所以,这就是为什么我们看到接下来的两行输出

Derived tell name:Derived
Derived print name:Derived

这背后的故事很长!

答案 1 :(得分:0)

执行从Derived.main开始。这将创建Derived的新实例,因此将调用Derived构造函数。首先调用Base构造函数,该构造函数初始化Base子对象的name,然后调用tellName。由于动态调度,调用的tellNameDerived.tellName而非Base.tellName。此打印的文本引用尚未初始化的Derived子对象的name,而不是已初始化的Base子对象的name,因此打印"Derived tell name:null"。控件将在Base构造函数中继续,然后使用printName子对象的Base调用name。由于动态调度,会调用Derived.printName。它打印的name是它的参数,(正如我们刚才看到的)是来自name子对象的Base。因此,它打印"Derived print name:base",因为Base子对象的name之前已初始化为"base"Base构造函数现已完成,控件将在Derived构造函数中恢复。现在,这会将Derived子对象的name初始化为"Derived",然后以明显的方式调用Derived.tellNameDerived.printName,并观察结果。

作为一个额外的观察,值得注意的是,这里出现的问题是因为Java在构造函数中动态调度虚拟调用;其他语言如C ++不会,例如见:

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