skip to content

How does super() work in constructors, and what are the rules for constructor chaining in an inheritance hierarchy?

level: middleimportance: must knowfreq 78%

answer

  1. super()/this() must be the first statement
  2. no explicit call → implicit no-arg super()
  3. parent needs an accessible no-arg ctor or you must call super(args)
  4. bodies run top-down (Object first)
  5. this() and super() are mutually exclusive

basics

~10 s

super(...) calls a parent constructor and must be the first statement in a subclass constructor. If you don't write it, Java inserts a no-arg super() automatically so the parent is always initialized first.

solid answer

~40 s

Constructing a subclass always constructs the superclass part first. The compiler ensures this by requiring that the first statement of every constructor be either super(args) (an explicit parent-constructor call) or this(args) (another constructor in the same class). If you write neither, the compiler inserts an implicit no-argument super(). This produces a chain: each constructor calls up the hierarchy until Object, then bodies run top-down. A key gotcha: if the parent has no accessible no-arg constructor (because it only declares parameterized ones), the subclass must call super(args) explicitly or it won't compile. Because super()/this() must be first, you cannot reference instance fields or run logic before it. This guarantees the parent's invariants are established before the subclass adds its own state.

code

java · 14 lines
java
class Animal {
    final String name;
    Animal(String name) { this.name = name; }   // only a parameterized ctor
}

class Dog extends Animal {
    Dog(String name) {
        super(name);   // REQUIRED: no no-arg Animal() exists
        // ...
    }
}

// class Cat extends Animal { Cat() {} }  // COMPILE ERROR:
// implicit super() has no matching Animal()

go deeper

for a junior

Knows super(args) calls a parent constructor and that it must come first.

for a middle

Explains implicit super(), the no-arg-constructor compile error, this() vs super(), and top-down body execution.

for a senior

Reasons about initialization ordering, why overridable calls in constructors are dangerous, and final-field initialization guarantees through the chain.

for a principal

Designs constructor/factory strategies that keep object initialization safe and invariant-preserving across deep hierarchies, and steers teams away from fragile base-class construction patterns.

## The core guarantee: parents are built first A Java object of a subclass *contains* the state of its superclass. For the object to be valid, the superclass portion must be initialized **before** the subclass portion. Java enforces this through **constructor chaining**. ## super() — calling a parent constructor Inside a subclass constructor you may call a superclass constructor with `super(args)`. This must be the **very first statement** in the constructor body: ```java class Animal { final String name; Animal(String name) { this.name = name; } } class Dog extends Animal { Dog(String name) { super(name); // must be first // subclass-specific init follows } } ``` ## The implicit super() If you do **not** write `super(...)` or `this(...)` as the first statement, the compiler automatically inserts a call to the parent's **no-argument** constructor, `super()`. So this: ```java class Cat extends Animal { Cat() { } } ``` is treated as if you wrote `Cat() { super(); }`. ## The classic compile error The implicit `super()` only works if the parent actually *has* an accessible no-arg constructor. If `Animal` declares only `Animal(String name)` and no no-arg constructor, then `Cat() {}` fails to compile, because the inserted `super()` matches nothing. The fix is to call an existing parent constructor explicitly: `Cat() { super("unknown"); }`. (Remember: once you declare any constructor, Java no longer gives you a free default no-arg one.) ## this() vs super() The first statement can instead be `this(args)`, which delegates to **another constructor in the same class**. That constructor, in turn, must eventually reach a `super(...)`. You can use `this()` *or* `super()` as the first statement, never both — they are mutually exclusive because both must occupy the first-statement slot. ## The full chain and ordering For `new Dog("Rex")` with hierarchy `Object <- Animal <- Dog`: 1. `Dog`'s constructor calls `super(name)` → `Animal`'s constructor, 2. which (implicitly) calls `super()` → `Object`'s constructor, 3. `Object`'s body runs, 4. then `Animal`'s body runs, 5. then `Dog`'s body runs. So constructor **bodies execute top-down** (most general first), even though the calls were written bottom-up. ## Why super()/this() must be first Because the parent must be initialized before you can safely use its state, Java forbids any statement before `super()`/`this()`. You therefore cannot read instance fields or call instance methods of the object before the super call (the object isn't fully formed). (A modern refinement: recent Java versions relax this slightly to allow some preliminary statements that don't reference the instance, but the conceptual rule — parent first — stands.) ## A subtle danger: calling overridable methods from a constructor If a superclass constructor calls an overridable method, the subclass override runs **before the subclass constructor body**, so it sees uninitialized subclass fields. Avoid calling overridable methods from constructors.

  • Why does Cat() {} fail to compile if Animal only has Animal(String)?
    The compiler inserts an implicit no-arg super(), but Animal has no no-arg constructor, so the call resolves to nothing and compilation fails. You must call super(args) explicitly.
  • In what order do constructor bodies actually execute?
    Top-down: Object's body first, then each subclass down to the most-derived class. The super(...) calls chain upward, but the bodies unwind and run from the root downward.
  • Why is calling an overridable method inside a constructor risky?
    Dynamic dispatch runs the subclass override while the subclass's own fields are still uninitialized, leading to nulls or wrong values.

saying these in an interview costs you the question

  • Putting statements before super()/this()
  • Assuming a parent always has a no-arg constructor
  • Saying constructors are inherited (they are not — they chain)
  • Thinking subclass body runs before the parent body
  • Using both this() and super() in one constructor

context