-1

类基础:

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

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

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

4

2 回答 2

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

这背后的故事很长!

于 2013-10-14T15:36:58.953 回答
0

执行开始于Derived.main. 这会创建 的新实例Derived,因此Derived会调用构造函数。这首先调用Base构造函数,该构造函数初始化Base子对象name,然后调用tellName. 由于动态调度,tellName称为 isDerived.tellName和 not Base.tellName。此打印的文本是指尚未初始化的子对象的 ,而不是已初始化的Derived子对象的,因此被打印。控制在构造函数中恢复,接下来使用子对象的. 由于动态调度,被调用。这nameBasename"Derived tell name:null"BaseprintNameBasenameDerived.printNamename它打印的是它的参数,它(正如我们刚刚看到的)是name来自Base子对象的。因此它打印"Derived print name:base",因为Base子对象name先前已初始化为"base"。构造函数现在已经完成,并且控制在构造函数Base中恢复Derived。现在,这将初始化Derived子对象的nameto "Derived",然后以明显的方式调用Derived.tellNameand Derived.printName,并使用观察到的结果。

作为一个额外的观察,值得注意的是这里出现的问题是因为 Java 在构造函数中动态调度虚拟调用。其他语言(例如 C++)没有,例如,请参阅:

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

于 2013-10-14T15:45:34.480 回答