我有以下代码:

class Egg2 {
    protected class Yolk {
        public Yolk() { System.out.println("Egg2.Yolk()");}
        public void f() { System.out.println("Egg2.Yolk.f()");         }
    }
    private Yolk y = new Yolk();
    public Egg2() { System.out.println("New Egg2()");}
    public void insertYolk(Yolk yy) { y = yy; }
    public void g() { y.f(); }
}

public class BigEgg2 extends Egg2 {
    public class Yolk extends Egg2.Yolk {
        public Yolk() { System.out.println("BigEgg2.Yolk"); }
        public void f() { System.out.println("BigEgg2.Yolk.f()"); }

    }
    public BigEgg2() { insertYolk(new Yolk()); }

    public static void main(String[] args) {
        Egg2 e2 = new BigEgg2();
        e2.g();
    }

}


输出为:

Egg2.Yolk()
New Egg2()
Egg2.Yolk()
BigEgg2.Yolk
BigEgg2.Yolk.f()


问题:现在我无法确定如何初始化此类对象和类。
我认为顺序应该是这样的:


创建新链接e2:Egg2 e2 = new BigEgg2();
转到构造函数:public BigEgg2(){insertYolk(new Yolk()); }
由于继承编译器的原因,请转到:public Yolk(){System.out.println(“ Egg2.Yolk()”);},此后,我们看到输出:Egg2.Yolk();。
然后,编译器调用此方法:public void insertYolk(Yolk yy){y = yy; },其中Egg2.Yolk.y = BigEgg2.Yolk.yy(比喻说)。
在这一步,我无法弄清楚下一个输出结果为何:

新蛋2

Egg2.Yolk()

BigEgg2.Yolk


此阶段的外观如何?

为什么会这样?

最佳答案

用超类构造函数调用类的构造函数时,发生了很多事情,而且它们都具有实例变量初始化器。

您的BigEgg2构造函数不会显式调用任何超类构造函数,因此编译器会插入对Egg2的默认构造函数的调用。 (同样的情况适用于调用Egg2构造函数的Object构造函数,但该函数不会打印任何内容。)

对超类构造函数的调用完成后,将运行超类的实例初始化器(如果有)。这意味着任何实例变量都在声明它们的地方初始化。在这里,为实例变量Egg2.Yolk创建了y的实例。这是输出Egg2.Yolk()的第一行。

然后,最终执行超类构造函数的主体。这是输出New Egg2()的第二行。

BigEgg2类具有自己的Yolk类,以实例化要在其自己的构造函数中传递给insertYolk的情况。它创建一个Yolk,该YolkEgg2中将嵌套类Egg2.Yolk子类化。首先调用超类构造函数,该构造函数引用Egg2.Yolk()类。这是输出BigEgg2.Yolk的第三行。请注意,这是与输出的第一行相同的打印语句。

y的该对象在超类方法Egg2.insertYolk中分配给实例变量BigEgg2.Yolk。这发生在BigEgg2.Yolk构造函数的主体中。 BigEgg2.Yolk构造函数负责输出y的第四行。请注意,BigEgg2.Yolk变量现在引用的是main的实例。至此,Egg2 e2 = new BigEgg2();第一行的执行完成:e2.g()

调用g()时,您正在调用BigEgg2Egg2继承的y.f()方法,该方法调用y,其中Egg2.Yolkf()。由于多态性,在BigEgg2.Yolk中调用BigEgg2.Yolk.f()方法。这是输出的第五行。

10-07 12:29