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.
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 constructorStep by step: what happens in new Puppy()
- Memory for the whole Puppy object is set aside. It includes space for any attributes declared in Animal, Dog and Puppy.
- The Puppy constructor starts. Its first line is an invisible
super();, added by the compiler, so it calls the Dog constructor straight away. - The Dog constructor's first line is
super();, so it calls the Animal constructor. - The Animal constructor calls
Object(), which finishes at once. Then Animal's body runs and prints 1. - Control returns to Dog, whose body prints 2.
- 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:
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.