Flexible Constructor Bodies

Naveen AnamaneniUpdated · 4 min read

For 30 years, a Java constructor that called super(...) or this(...) had to make that call its very first statement. If you wanted to check an argument first, you couldn't; you had to squeeze the check into a helper method inside the call. Java 25 (JEP 513) relaxed that rule. A constructor can now run ordinary code before calling super(...) or this(...), as long as that code doesn't touch the object being built.

Validate Before Calling super

Here SavingsAccount requires a minimum balance. It checks the argument before asking the parent class to build its part:

Flex.java▶ Try it
public class Flex {
    static class Account {
        final String holder;
        final long balance;
 
        Account(String holder, long balance) {
            this.holder = holder;
            this.balance = balance;
        }
    }
 
    static class SavingsAccount extends Account {
        SavingsAccount(String holder, long balance) {
            if (balance < 1000) {
                throw new IllegalArgumentException("Need at least Rs. 1000");
            }
            super(holder.trim(), balance);
        }
    }
 
    public static void main(String[] args) {
        Account s = new SavingsAccount("  Navika ", 5000);
        System.out.println("[" + s.holder + "] Rs. " + s.balance);
        try {
            new SavingsAccount("Advitha", 10);
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }
}
Output
[Navika] Rs. 5000
Need at least Rs. 1000

How it works

  1. SavingsAccount extends Account makes it a subclass (see "Inheritance in Java"). Its constructor must call the parent's constructor with super(...).
  2. Lines 14 to 16 run before super(...): an invalid balance is rejected before any part of the object is built.
  3. Line 17 calls super(...) with a cleaned-up name. On Java 24 and earlier, this constructor didn't compile.

Try it yourself: move the if block below the super(...) line. Does it still work? Which version rejects bad input earlier?

What the Prologue May and May Not Do

Before super(...): prepare. After super(...): use the object
In the prologue (before super/this)Allowed?
Check arguments, throw exceptionsYes
Declare and compute local variablesYes
Call static methodsYes
Assign this class's own fields (this.x = ...)Yes
Read fields, call instance methods, pass this anywhereNo

The object isn't built yet, so reading it is unsafe. The compiler stops you:

Compiler output
FlexThis.java:1: error: cannot reference this before supertype constructor has been called
class A { int x; A() { System.out.println(this.x); super(); } }
                                          ^

Why Assigning Fields Early Helps

A parent constructor sometimes calls a method that the subclass has overridden (see "Method Overriding in Java"). Before Java 25, that method could see the subclass's fields still at their default values, because the subclass hadn't set them yet. Now the subclass can assign its fields in the prologue, before super(...) runs, so even code called from the parent sees real values.

Common Mistakes

Using this in the prologue. Reading a field or calling an instance method before super(...) doesn't compile.

Expecting it on older Java. Statements before super(...) fail to compile on Java 24 and earlier (it was a preview feature in 22 to 24).

Calling super(...) twice or inside an if. A constructor still has exactly one super(...) or this(...) call, at the top level of its body.

Practice

  1. Easy: In the earlier BankAccount chain from "Constructor Overloading and Constructor Chaining", add a check before this(holder, 0) that rejects an empty name.
  2. Harder: Write a parent class Shape(String name) and a subclass Circle(double radius) that rejects a negative radius before calling super("circle").

Quick check: Flexible constructor bodies

4 questions
1From which version can statements appear before super(...)?
2Which is allowed before super(...)?
3Can the prologue assign the class's own fields?
4What error do you get for reading this.x before super()?

Key Takeaways

Was this tutorial helpful?

Lesson 103 of 482