Back to Constructors & this/super
Q1Question 1 of 3

What are the rules for this() and super() in constructors?

Key Concepts
  • this() calls another constructor in the SAME class – used for constructor chaining
  • super() calls the PARENT class constructor – ensures parent is initialized first
  • this() or super() must be the FIRST statement in the constructor – you cannot have both
  • If you write neither, the compiler inserts super() (no-arg) automatically
  • If the parent has no no-arg constructor, you MUST explicitly call super(args) or the code does not compile
  • Construction order: parent first (super), then child – fields and init blocks run between super() and the rest of the constructor body

Definition

this() delegates to another constructor in the same class. super() calls the parent constructor. One of them must be the first statement, and if you write neither, super() is inserted automatically.

Constructor delegation rules:

  • this(args) calls another constructor in the same class. Used to avoid duplicating initialization logic.
  • super(args) calls a parent class constructor. Ensures the parent is fully initialized before the child.
  • Must be the first statement. You cannot put any code before this() or super(), and you cannot use both in the same constructor.
  • Implicit super(). If you write neither this() nor super(), the compiler inserts super() (no-arg) automatically.

When opening a new bank branch (child class), the head office (parent class) must be set up first (super()). You can also delegate within the branch: the full-service opening procedure (one constructor) can delegate to a basic setup procedure (this()) to reuse common steps. But the very first thing that happens must be either calling head office or calling the basic setup.

Understanding the Concepts

How does super() work?

JAVA
public class Account {
    private final String accountId;
    private BigDecimal balance;

    public Account(String accountId, BigDecimal balance) {
        this.accountId = accountId;
        this.balance = balance;
        System.out.println("Account constructor: " + accountId);
    }
}

public class SavingsAccount extends Account {
    private double interestRate;

    public SavingsAccount(String accountId, BigDecimal balance, double rate) {
        super(accountId, balance);  // MUST be first – initializes parent fields
        this.interestRate = rate;
        System.out.println("SavingsAccount constructor: rate=" + rate);
    }
}

new SavingsAccount("SAV2001", new BigDecimal("500000"), 4.0);
// Output:
// Account constructor: SAV2001
// SavingsAccount constructor: rate=4.0

The parent constructor runs first, then the child constructor body.

How does this() work?

JAVA
public class Account {
    private final String accountId;
    private BigDecimal balance;
    private boolean active;

    // Full constructor
    public Account(String accountId, BigDecimal balance) {
        this.accountId = accountId;
        this.balance = balance;
        this.active = true;
        System.out.println("Full constructor");
    }

    // Convenience constructor delegates to the full one
    public Account(String accountId) {
        this(accountId, BigDecimal.ZERO);  // this() calls the other constructor
        System.out.println("Convenience constructor");
    }
}

new Account("SAV2001");
// Output:
// Full constructor
// Convenience constructor

this() avoids duplicating the initialization logic.

What if the parent has no no-arg constructor?

JAVA
public class Account {
    // Only a parameterized constructor – no no-arg constructor
    public Account(String accountId) {
        System.out.println("Account: " + accountId);
    }
}

public class SavingsAccount extends Account {
    // This does NOT compile:
    // public SavingsAccount() { }  // ERROR: implicit super() expects no-arg, but none exists

    // This compiles: explicitly call super with args
    public SavingsAccount(String accountId, double rate) {
        super(accountId);  // explicit call to parent's parameterized constructor
    }
}

If you do not write any constructor in Account, Java provides a default no-arg constructor. But the moment you write any constructor, the default disappears.

Can you use both this() and super()?

JAVA
public class SavingsAccount extends Account {
    // This does NOT compile:
    // public SavingsAccount(String id) {
    //     super(id);      // first statement
    //     this(id, 4.0);  // ERROR: this() must also be first statement
    // }

    // The solution: chain this() to another constructor that calls super()
    public SavingsAccount(String id) {
        this(id, 4.0);  // delegates to the other constructor
    }

    public SavingsAccount(String id, double rate) {
        super(id);  // this constructor calls super()
        this.rate = rate;
    }
}

Only one can be first. Use chaining to get both effects.

What is the complete construction order?

TEXT
1. super() runs first (parent constructor)
2. Parent's field initializers and instance blocks run (in source order)
3. Parent's constructor body runs
4. Child's field initializers and instance blocks run
5. Child's constructor body runs
JAVA
public class Account {
    private boolean active = true;  // step 2: field initializer
    { System.out.println("Account init block"); }  // step 2: init block

    public Account(String id) {
        System.out.println("Account constructor");  // step 3
    }
}

public class SavingsAccount extends Account {
    private double rate = 4.0;  // step 4: field initializer
    { System.out.println("Savings init block"); }  // step 4

    public SavingsAccount(String id) {
        super(id);  // step 1: triggers parent construction
        System.out.println("Savings constructor");  // step 5
    }
}

new SavingsAccount("SAV2001");
// Output:
// Account init block
// Account constructor
// Savings init block
// Savings constructor

What are common mistakes?

  • Forgetting super() when parent has no no-arg constructor. Compiler error: "no suitable constructor found."
  • Putting code before this() or super(). They must be the very first statement.
  • Circular this() calls. A() { this(1); } and A(int x) { this(); } creates infinite recursion. Compiler catches this.
  • Calling instance methods before super(). The object is not fully initialized yet – leads to NullPointerException or wrong state.

What should a senior engineer know?

  • Records auto-generate a canonical constructor. record Account(String id, BigDecimal balance) {} has an implicit all-args constructor. You can add a compact constructor for validation.
  • Lombok @AllArgsConstructor / @Builder generates constructors. Understand what they produce under the hood.
  • In Spring, constructor injection is the preferred DI pattern: public AccountService(AccountRepository repo) { this.repo = repo; }. Spring calls the constructor and injects dependencies.

Visual Overview

DIAGRAM
  new SavingsAccount("SAV2001")
    │
    ▼
  SavingsAccount(String id)
    │ super(id) ← must be first
    ▼
  Account(String id)
    │ super() ← implicit call to Object()
    ▼
  Object() runs
    ▼
  Account field initializers + init blocks
    ▼
  Account constructor body
    ▼
  SavingsAccount field initializers + init blocks
    ▼
  SavingsAccount constructor body
    ▼
  Object fully constructed

  Rules:
    this() or super() must be FIRST statement
    Cannot use both in one constructor
    If neither written → implicit super()
    Parent no-arg missing + no explicit super(args) → COMPILE ERROR

Key Takeaway

this() delegates to another constructor in the same class, and super() calls the parent constructor. One of them must be the first statement in every constructor. If you write neither, the compiler inserts super() automatically.

The construction order is always parent first: super() runs, then the parent's field initializers and init blocks, then the parent's constructor body, then the child's field initializers and init blocks, then the child's constructor body.

If the parent class has no no-arg constructor, you must explicitly call super(args) or the code does not compile. Use this() chaining to avoid duplicating initialization logic across multiple constructors.

One sentence to remember: this() or super() must be the first statement, if neither is written super() is implicit, and the parent is always constructed before the child.

---

Share
Use ← → arrow keys to navigate