msn013
msn013

Reputation: 103

What the reason of such output "println" order? How to initialize object in this code?

I had this code:

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

}

Output is:

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

Issue: now I can't make out how such objects and classes were initialized. I thought the order should be like this:

  1. Create new link e2: Egg2 e2 = new BigEgg2();

  2. Go to constructor: public BigEgg2() { insertYolk(new Yolk()); }

  3. Because of inheritance compiler go to: public Yolk() { System.out.println("Egg2.Yolk()");}, after that we saw output: Egg2.Yolk();

  4. Then compiler invoked this method: public void insertYolk(Yolk yy) { y = yy; }, where Egg2.Yolk.y = BigEgg2.Yolk.yy (figuratively speaking).

  5. At this step I can't figure out why the next output result will be:

    New Egg2()

    Egg2.Yolk()

    BigEgg2.Yolk

What's appearance at this stage?

Why it go like this?

Upvotes: 0

Views: 49

Answers (1)

rgettman
rgettman

Reputation: 178263

A lot is going on when you call a constructor of a class with a superclass constructor, and they both have instance variable initializers.

Your constructor for BigEgg2 doesn't explicitly call any superclass constructor, so the compiler inserted a call to the default constructor for Egg2. (The same thing applies to the Egg2 constructor calling the Object constructor, but that one doesn't print anything.)

After the call to the superclass constructor completes, instance initializers for the superclass, if any, are run. This means any instance variables initialized where they are declared. Here, an instance of Egg2.Yolk is created for the instance variable y. This is the first line of output Egg2.Yolk().

Then the body of the superclass constructor is finally executed. This is the second line of output New Egg2().

The BigEgg2 class has its own Yolk class to instantiate to be passed to insertYolk in its own constructor. It creates a Yolk that subclasses the nested class Yolk in Egg2. The superclass constructor is called first, which refers to the Egg2.Yolk class. This is the third line of output Egg2.Yolk(). Note that this is the same print statement as the first line of output.

This object of class BigEgg2.Yolk is assigned to the instance variable y in the superclass method Egg2.insertYolk. This occurs in the body of the BigEgg2.Yolk constructor. The BigEgg2.Yolk constructor is responsible for the fourth line of output BigEgg2.Yolk. Note that the y variable is now referring to an instance of BigEgg2.Yolk. At this point the execution of the first line of main is complete: Egg2 e2 = new BigEgg2();.

When you call e2.g(), you are calling the g() method that BigEgg2 inherits from Egg2, which calls y.f(), where y is a Egg2.Yolk. Because of polymorphism, the f() method in BigEgg2.Yolk is called. This is the fifth line of output BigEgg2.Yolk.f().

Upvotes: 1

Related Questions