How do I Initialize Fields Before Calling super() in Java 25?

Java 25 includes JEP 513: Flexible Constructor Bodies. This feature changes a long-standing rule: before Java 22, the call to super(...) or this(...) had to be the very first statement in a constructor. Starting with Java 25, you can execute statements before the explicit constructor invocation — including initializing your own instance fields.

This is especially useful when a field’s value must be ready before the superclass constructor runs (for example, if the superclass calls an overridden method that reads that field).


The Old Restriction (Pre-Java 22)

public class Child extends Parent {
    private final int value;

    public Child(int input) {
        // Compile error before Java 22:
        // "call to super must be first statement in constructor"
        this.value = input * 2;
        super(computeSomething(input));
    }
}

The Java 25 Way: Prologue Before super(...)

With flexible constructor bodies, the constructor is split into two regions:

  1. Prologue — statements that run before super(...) or this(...).
  2. Epilogue — the usual constructor body that runs after.

Example 1: Initializing a Field Before super()

public class Parent {
    public Parent() {
        // Calls a method that subclasses may override
        describe();
    }

    protected void describe() {
        System.out.println("Parent describing");
    }
}

public class Child extends Parent {
    private final String label;

    public Child(String label) {
        // Java 25: initialize field BEFORE super()
        this.label = label;
        super();
    }

    @Override
    protected void describe() {
        // Safe: 'label' is already assigned, no NPE
        System.out.println("Child label = " + label);
    }
}

Before Java 25, label would still be null when Parent‘s constructor called the overridden describe(). Now you can assign it first.


The Prologue Rules You Must Follow

Inside the prologue (code before super(...) / this(...)), the compiler enforces strict rules to keep things safe:

Allowed Not Allowed
Assign to fields declared in this class Read fields of this
Validate / transform constructor arguments Call instance methods on this
Compute values, throw exceptions, use if, switch, loops, try Use this or super as a value
Call static methods Access inherited (superclass) fields

Example 2: Combining Validation and Field Init

public class Rectangle {
    protected final int area;

    public Rectangle(int area) {
        this.area = area;
    }
}

public class Square extends Rectangle {
    private final int side;

    public Square(int side) {
        // Prologue: validate, then initialize own field, then call super
        if (side <= 0) {
            throw new IllegalArgumentException("side must be positive");
        }
        this.side = side;          // assigning own field is allowed
        super(side * side);        // explicit constructor invocation
        // Epilogue starts here — 'this' is fully available
        System.out.println("Created Square with side=" + side + ", area=" + area);
    }
}

Example 3: Why This Matters — Fixing the “Leaked this” Problem

public abstract class Shape {
    public Shape() {
        render(); // calls subclass override during construction
    }
    protected abstract void render();
}

public class Circle extends Shape {
    private final double radius;

    public Circle(double radius) {
        this.radius = radius; // set before super() runs render()
        super();
    }

    @Override
    protected void render() {
        // Now 'radius' has its intended value, not 0.0
        System.out.println("Rendering circle with radius " + radius);
    }
}

Compiling and Running on Java 25

Since JEP 513 is a final feature in Java 25, no --enable-preview flag is required:

javac --release 25 Child.java Parent.java
java Child

Key Takeaways

  • You can now place statements — including assignments to your own fields — before super(...) or this(...).
  • The prologue cannot read this or call instance methods; it can only write to fields of the current class.
  • Exactly one explicit constructor invocation (super(...) or this(...)) is still required (implicitly or explicitly).
  • This feature is final in Java 25 — no preview flags needed.

This cleanly resolves cases where a subclass field needed to exist before the parent constructor ran, without resorting to static helpers or awkward factory methods.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.