skip to content

When does the compiler's implicit super() insertion fail, and how do you fix it?

level: middleimportance: should knowfreq 58%

answer

  1. Default no-arg ctor exists ONLY if you declare zero ctors
  2. Implicit super() always calls the NO-ARG parent ctor
  3. Parent with only parameterized ctors -> subclass fails to compile
  4. Fix: explicit super(args) OR add a no-arg ctor to the parent
  5. private no-arg ctor is also inaccessible to subclasses

basics

~10 s

The compiler auto-adds super() only if the parent has a no-arg constructor. If the parent only has constructors that take arguments, you must call super(...) yourself with valid arguments, or the subclass won't compile.

solid answer

~50 s

When a subclass constructor doesn't explicitly call this(...) or super(...), the compiler inserts an implicit no-argument super(). That insertion succeeds only if the direct parent has an accessible no-argument constructor. The catch: a class only gets the implicit default no-arg constructor when it declares no constructors at all. So the moment a parent class declares any constructor with parameters and no explicit no-arg one, it loses its no-arg constructor, and the implicit super() insertion in subclasses fails to compile. The fix is one of: explicitly call super(args) with valid arguments as the first statement of every subclass constructor; or add an explicit no-arg constructor to the parent. Accessibility also matters: if the parent's no-arg constructor is private, subclasses outside that class cannot call it, so the same error appears. This is a common gotcha when adding a parameterized constructor to a widely-extended base class.

go deeper

for a junior

Knows the compiler adds super() automatically and that a parent needs a no-arg constructor for it to work.

for a middle

Explains that declaring any constructor removes the default no-arg one, why the subclass then fails, and the explicit-super(args) fix.

for a senior

Recognizes the source-incompatibility of adding a base-class constructor and accounts for accessibility and framework (JPA/serialization) constraints.

for a principal

Sets API-evolution policy for base classes, anticipating subclass/framework breakage, and prefers composition or final classes to avoid fragile inheritance contracts.

## Background you need A **constructor** initializes a new object. If a class declares **no constructors at all**, the compiler gives it a **default constructor**: a `public` (actually same access as the class) no-argument constructor that just calls `super()`. The instant you declare *any* constructor yourself, that freebie disappears — the class now has **only** the constructors you wrote. **Inheritance:** a subclass declared `class B extends A` must, during construction, initialize the `A` part of the object first by calling one of `A`'s constructors via `super(...)`. ## The implicit super() rule If a subclass constructor's first statement is **not** an explicit `this(...)` or `super(...)`, the compiler inserts a **no-argument** `super()` for you. Crucially, it always inserts the *no-arg* form — it cannot guess which arguments to pass. ## Where it breaks The auto-inserted `super()` needs the parent to actually *have* an accessible no-arg constructor. It breaks in two situations: 1. **Parent declared only parameterized constructors.** Because declaring any constructor removes the default one, the parent no longer has a no-arg constructor, so `super()` has nothing to call. ```java class A { A(int x) { } // declares a ctor -> no default no-arg ctor exists } class B extends A { B() { } // ERROR: implicit super() finds no A() to call } ``` The compiler error reads roughly: *"there is no default constructor available in A"*. 2. **Parent's no-arg constructor is inaccessible** (e.g. `private`). It exists but the subclass can't legally call it, so the implicit (or even explicit) `super()` is rejected. ## The fixes - **Call super(args) explicitly** in every subclass constructor, passing valid arguments: ```java class B extends A { B() { super(0); } // OK: explicitly supplies the argument A needs } ``` - **Add an explicit no-arg constructor to the parent**, if a no-arg construction makes sense: ```java class A { A() { } // restores a no-arg ctor A(int x) { } } ``` - **Loosen accessibility** of the parent's no-arg constructor if it was too restrictive (e.g. make it `protected` so subclasses can call it). ## Why this surprises people The failure shows up in the *subclass* even though the *parent* changed. Adding a parameterized constructor to a base class is a **source-incompatible** change for every subclass that relied on the implicit no-arg `super()`. This is exactly why API designers think twice before adding constructors to widely-extended base classes, and why frameworks (e.g. JPA entities, serialization) often require an explicit no-arg constructor to keep reflection-based instantiation working.

  • Why does adding a parameterized constructor to a base class break existing subclasses?
    Declaring any constructor removes the compiler-generated default no-arg constructor. Subclasses that relied on the implicit no-arg super() now have nothing to call, so they fail to compile until they call super(args) explicitly or the parent regains a no-arg constructor.
  • Why do JPA/Hibernate entities usually need an explicit no-arg constructor?
    These frameworks instantiate entities reflectively by calling the no-arg constructor, then set fields. If the entity declares only parameterized constructors, the no-arg one is gone and instantiation fails, so you add an explicit (often protected) no-arg constructor.

saying these in an interview costs you the question

  • Assuming every class always has a usable no-arg constructor
  • Thinking the implicit super() can pass arguments
  • Blaming the subclass code without noticing the parent lost its default ctor
  • Forgetting that a private no-arg constructor is unreachable from subclasses

context