When does the compiler's implicit super() insertion fail, and how do you fix it?
answer
- Default no-arg ctor exists ONLY if you declare zero ctors
- Implicit super() always calls the NO-ARG parent ctor
- Parent with only parameterized ctors -> subclass fails to compile
- Fix: explicit super(args) OR add a no-arg ctor to the parent
- private no-arg ctor is also inaccessible to subclasses
basics
~10 sThe 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 sWhen 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
Knows the compiler adds super() automatically and that a parent needs a no-arg constructor for it to work.
Explains that declaring any constructor removes the default no-arg one, why the subclass then fails, and the explicit-super(args) fix.
Recognizes the source-incompatibility of adding a base-class constructor and accounts for accessibility and framework (JPA/serialization) constraints.
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