Unit 3 · OOP Concepts

3.5.5Constructor order

When you create a Dog, the Dog constructor is called first, but its first action is super(...), so the Animal constructor (and before it, the Object constructor) finishes first. Parents are built before children.

new Dog("Rex")Object()java.lang.Object1Animal(name)sets name2Dog(name)rest of Dog's body3constructor bodies finish in this order: parent first, child lastDog(name) calls super(name) as its first statement; Animal's constructorimplicitly calls Object(), so the most general part is built first
Constructor order: parents are built before children
Java
class Animal {
    Animal() { System.out.println("1. Animal constructor"); }
}
class Dog extends Animal {
    Dog() {
        super();   // added by the compiler if you leave it out
        System.out.println("2. Dog constructor");
    }
}
class Puppy extends Dog {
    Puppy() { System.out.println("3. Puppy constructor"); }
}

new Puppy();
// 1. Animal constructor
// 2. Dog constructor
// 3. Puppy constructor

Step by step: what happens in new Puppy()

  1. Memory for the whole Puppy object is set aside. It includes space for any attributes declared in Animal, Dog and Puppy.
  2. The Puppy constructor starts. Its first line is an invisible super();, added by the compiler, so it calls the Dog constructor straight away.
  3. The Dog constructor's first line is super();, so it calls the Animal constructor.
  4. The Animal constructor calls Object(), which finishes at once. Then Animal's body runs and prints 1.
  5. Control returns to Dog, whose body prints 2.
  6. Control returns to Puppy, whose body prints 3.

The calls go from the bottom up (Puppy, Dog, Animal), but the constructor bodies finish from the top down (Animal, Dog, Puppy). This makes sense: a Dog's constructor may need the Animal part to be ready already, just as a house's walls need the foundation to be built first.

Passing values up the chain

Usually each level needs its own values. Each constructor passes the parent's values up with super(...) and keeps its own:

Java
class Animal {
    protected String name;
    Animal(String name) { this.name = name; }
}
class Dog extends Animal {
    protected String breed;
    Dog(String name, String breed) {
        super(name);          // Animal sets name
        this.breed = breed;   // Dog sets breed
    }
}

this(...) and super(...)

Both must be the first statement of a constructor, so a constructor can contain one of them, but not both. If a constructor starts with this(...), the call to super(...) happens in the other constructor that it calls. If it starts with neither, the compiler inserts super();.

Do not call overridable methods from a constructor. If Animal's constructor calls a method that Dog overrides, Dog's version runs before Dog's own constructor body has set Dog's attributes, so it sees default values (null or 0). Keep constructors simple: set the attributes and nothing more.

Remember

  • Every constructor starts by calling its parent's constructor, whether you write super(...) or not.
  • Parents are built before children: constructor bodies finish from the top of the hierarchy down.