Topic 58 of 119 6. Object-Oriented Programming in Java Interactive Tutorial

Constructor Chaining in Java: Using this() and super

17 mins read Last updated: 22 Aug 2026 28,947 views

Direct Answer & Core Concept

Constructor chaining means one constructor delegates its work to another, either in the same class with this(...) or in the direct parent with super(...). The reason it exists is that a constructor cannot return early, so there is no other way to reuse another constructor without duplicating its code. The ordering rules are strict:
  • this(...) and super(...) must each be the first statement of the constructor body.
  • They cannot both appear in one constructor, because there is only one first position.
  • If neither is written, the compiler inserts an implicit super() with no arguments.
Main.java
Run Online
public Widget(String name, int width) {
    super(name);
    // parent runs first, always
    this.width = width;
    // subclass body runs second, always
}
So the execution order is fixed no matter how the code is arranged: parent constructor body, then subclass constructor body. A subclass can never do its own work before the parent is fully built. A common misconception is that super() merely initialises the parent fields. It runs the parent constructor, including any validation and any further chaining, so an entire hierarchy can execute before your first statement runs.

Detailed Explanation & Mechanics

1) Why the First Statement Rule Exists

Java runs constructor bodies from the base class downwards, and it cannot read a field of the current object before the parent constructor has run. Rather than let you bypass that, the language forbids it syntactically.

Main.java
Run Online
public class Widget extends Component {
    public Widget(String name) {
        // COMPILE ERROR: call to super must be the first statement
        System.out.println("starting");
        super(name);
    }
}

The restriction exists for safety, not style. If a subclass could run code first, it could read a parent field while that field still held its type default, which is exactly the kind of bug the ordering rule exists to prevent.

Because the call must come first, you cannot log, compute, or branch before it. A common workaround is a static factory method that validates and then returns a fully constructed object.

2) Chaining Within One Class Using this

this(...) delegates to a sibling constructor in the same class. Its main purpose is to avoid repeating defaults across overloads.

Main.java
Run Online
public class Session {
    private final String user;
    private final String role;
    private final boolean active;
    // THE CANONICAL CONSTRUCTOR, the single real implementation
    public Session(String user, String role, boolean active) {
        this.user = user;
        this.role = role;
        this.active = active;
    } // EVERY SHORTER PATH DELEGATES HERE
    public Session(String user) {
        this(user, "guest", true);
    } public Session(String user, String role) {
        this(user, role, true);
    }
}

Three constructors now exist, but the assignment logic is written once. Adding a field means editing one constructor rather than four. The overloading topic covers this pattern in more detail.

3) Chaining to the Parent Using super

super(...) invokes a constructor in the direct parent only. A grandparent is reached by the parent delegating in turn.

Main.java
Run Online
public class Shape {
    private final String name;
    public Shape(String name) {
        this.name = name;
    } public String getName() {
        return name;
    }
}public class Square extends Shape {
    private final double side;
    public Square(double side) {
        super("square");
        // mandatory, since Shape has no no-arg one
        this.side = side;
    }
}

Every level of the hierarchy is entered through its own constructor, so getName() already returns a usable value by the time the Square body begins.


Diagram showing execution order running from the topmost parent constructor down to the subclass body
Parent constructors always complete before any subclass constructor body runs.

4) The Rule That Surprises People Most

super(...) is not a field initialiser. It invokes a whole constructor, and that constructor may itself chain again.

Main.java
Run Online
public class A {
    public A() {
        System.out.println("A body");
    }
}public class B extends A {
    public B() {
        System.out.println("B body");
    }
}new B();
// prints: A body, then B body

There is no way to print before A body, because B has no statement that runs first. In a deep hierarchy the subclass body can execute several levels after the object was first allocated.

This also means a parent constructor can call an overridden method in the subclass before the subclass fields are assigned. That is legal, and it is one of the most dangerous bugs in Java, because the subclass sees default values.

5) Overridden Methods Run Too Early

Because the parent body runs first, any method call it makes is dynamically dispatched to the subclass override, whatever the static type says.

Main.java
Run Online
public class Vehicle {
    private final String label;
    public Vehicle(String label) {
        this.label = label;
        describe();
        // dispatches to Car.describe(), not Vehicle
    } protected void describe() {
        System.out.println("label = " + label);
    }
}public class Car extends Vehicle {
    private final int doors = 4;
    // NOT YET ASSIGNED when describe runs
    public Car() {
        super("car");
    } @Override protected void describe() {
        System.out.println("car " + label + " with " + doors + " doors");
    }
}

Running this prints car car with 0 doors. The field initialiser for doors has not executed yet, so the override observes zero.

PhaseWhat has happened
1Memory allocated, fields set to type defaults
2Parent constructor begins, super() satisfied
3Parent field initialisers and parent body run
4Subclass field initialisers run
5Subclass constructor body runs

The safe rule is simple: never call an overridable method from a constructor. Make it private, static, or final if a constructor genuinely needs it.

6) this and super Cannot Coexist

Each must be the first statement, and a constructor has exactly one first statement, so you must choose one.

Main.java
Run Online
public class Report extends Document {
    // COMPILE ERROR: two statements both claim to be first
    public Report(String title, String author) {
        this(author);
        super(title);
    }
}

The fix is to let the compiler place the super() call for you.

Main.java
Run Online
public class Report extends Document {
    public Report(String title, String author) {
        this(author);
        // the target constructor calls super itself
    } public Report(String author) {
        super("report");
        // implicit super() also works here
        setAuthor(author);
    } public void setAuthor(String author) {
        // assignment logic moved into a method, so this() is free to be first
    }
}

This is why factory or setter helpers appear in well-designed hierarchies: they remove the need for the constructor to contain two competing first statements.

7) When super Is Implicit

Omit both and the compiler inserts super() with no arguments. This is silent, and it fails at compile time only when the parent has no no-argument constructor.

Main.java
Run Online
public class Config {
    public Config() {
    }
}public class AppConfig extends Config {
    private final String url;
    // COMPILE ERROR: no matching super() is available
    public AppConfig(String url) {
        this.url = url;
    }
}

Compare with the default constructor topic, which covers why a parent with no declared constructor still accepts this call.

8) super Refers Only to the Direct Parent

Java has single inheritance, so super is always one level up. It never reaches a grandparent or an interface implementation.

Main.java
Run Online
public class Square extends Rectangle {
    public Square() {
        super(SIDE_LENGTH);
        // calls Rectangle, not some higher class
    } private static final int SIDE_LENGTH = 10;
}

The super keyword also reaches parent members, which is covered separately in the super keyword topic.

9) this Has a Second Meaning

Inside a constructor, this is overloaded between two roles. The disambiguation is positional: followed by ( it is a constructor call, otherwise it is the current object reference.

UsageMeaning
this(...)Delegate to another constructor
this.fieldThe current object reference
this.method()Call a method on the current object
this.field = xDisambiguates a shadowed parameter
Main.java
Run Online
public class Point {
    private int x;
    private int y;
    public Point(int x, int y) {
        this.x = x;
        // the field, not the parameter
        this.y = y;
    }
}

The this.x prefix is not mandatory, but it is the clearest signal that an assignment targets a field. Both this meanings are examined in the this keyword topic.

10) Records and Enums Follow Their Own Rules

A record compact constructor is different again: you do not declare the parameters, and you cannot add a super call at all.

Main.java
Run Online
// The compiler already wrote super(), so no chaining is allowed here
public record Money(long amountInCents) {
    public Money {
        if (amountInCents < 0L) {
            throw new IllegalArgumentException("Amount cannot be negative");
        }
    }
}

An enum is even more restricted, since it is final and cannot be extended.

Chaining stops at the first class in the hierarchy that declares no constructor, because that is where the compiler inserts an implicit super(). Any class below it can still chain, but only to its own parent.

11) Common Misconceptions

ClaimVerdict
this and super can both be usedFalse. Only one first statement exists.
You can log before calling superFalse. The call must come first.
super only assigns parent fieldsFalse. It runs the parent constructor.
A subclass body can run before the parentFalse. Parent always completes first.
Overridden methods called from a parent see subclass fieldsFalse. They see type defaults.
super reaches any ancestorFalse. Only the direct parent.
Omitting super skips the parentFalse. An implicit call is inserted.
Chaining works in a record constructorFalse. super is already supplied.

Frequently Asked Questions

Why must this() or super() be the first statement?


Because a subclass body cannot legally observe a parent object whose constructor has not finished. Rather than allow that, the language makes the delegation syntactically mandatory at the start. The rule is enforced by the compiler, not by convention.

What happens if I write neither this nor super?


The compiler inserts an implicit call to the parent no-argument constructor at the start of the constructor body. This fails at compile time only when the direct parent declares no no-argument constructor, which is a useful early warning rather than a runtime failure.

Can this() and super() appear in the same constructor?


No, because each must occupy the single first-statement position. To delegate to a sibling constructor while still initialising the parent, let the target constructor call super, and move any extra assignment work into a helper method.

In what order do chained constructors execute?


From the top of the hierarchy downward. Every parent constructor, including field initialisers and its own chained calls, completes before the subclass field initialisers run, and those complete before the subclass constructor body. The order is fixed regardless of how the calls are arranged.

Can a parent constructor call a method the subclass overrides?


Yes, and this is legal but dangerous. Method dispatch is dynamic, so the override runs even though the subclass has not initialised yet, and the override observes type defaults rather than assigned values. Mark such methods private, static, or final, or initialise from a factory method.

Does super reach beyond the direct parent?


No. Because Java supports single inheritance, super always refers to the direct superclass. A grandparent is reached only when the parent itself chains upward, and interfaces are never reached through super at all.

Is this() a method call?


No, it is a constructor delegation, and the language treats it specially by requiring the first-statement position. Following the opening parenthesis is what distinguishes it from this.field and this.method, which refer to the current object.

Why can a record constructor not call super?


The compiler has already generated a canonical constructor that invokes the parent no-argument constructor for you. Writing your own would duplicate that call, so the compact constructor form deliberately omits the parameters and forbids explicit chaining.

Runnable Code Example: Constructor Chaining in Java

Java 17+
Main.java
Run Online
// Shows same-class chaining with this(), parent chaining with super(),
// and the fixed order in which every level actually executes.
public class ConstructorChainingDemo {
    private static final String DEFAULT_ROLE = "guest";
    private static final boolean DEFAULT_ACTIVE = true;
    private static final String SQUARE_NAME = "square";
    private static final double DEFAULT_SIDE = 10.0;
    private static final String REPORT_TITLE = "report";
    private static final int DOOR_COUNT = 4;
    // LEVEL ONE, the base of the hierarchy
    public static class Shape {
        private final String name;
        public Shape(String name) {
            this.name = name;
            System.out.println("  Shape built: " + name);
        } public String getName() {
            return name;
        }
    } // LEVEL TWO, chains upward with super(), then chains sideways with this()
    public static class Square extends Shape {
        private final double side;
        // THE CANONICAL CONSTRUCTOR
        public Square(String name, double side) {
            super(name);
            // runs before anything below
            this.side = side;
            System.out.println("  Square built: side " + side);
        } public Square(String name) {
            this(name, DEFAULT_SIDE);
            // same-class delegation
        } public double getSide() {
            return side;
        }
    } // A PARENT WHOSE CONSTRUCTOR CALLS AN OVERRIDDEN METHOD,
    // which is legal and is exactly the trap this example demonstrates
    public static class Vehicle {
        private final String label;
        public Vehicle(String label) {
            this.label = label;
            describe();
            // dispatches to Car before Car is ready
        } protected void describe() {
            System.out.println("  Vehicle describes " + label);
        } public String getLabel() {
            return label;
        }
    } public static class Car extends Vehicle {
        // This initialiser has NOT run when the parent calls describe()
        private final int doors = DOOR_COUNT;
        private final boolean assembled;
        public Car(String label) {
            super(label);
            this.assembled = true;
        } @Override protected void describe() {
            // assembled is still false and doors reads as 0 at this point
            System.out.println("  Car describes " + getLabel() + " doors=" + doors + " assembled=" + assembled);
        }
    } // THIS() AND SUPER() CANNOT SHARE A CONSTRUCTOR,
    // so the sibling target supplies the super() call for us
    public static class Document {
        private String title;
        public Document(String title) {
            this.title = title;
            System.out.println("  Document built: " + title);
        } public String getTitle() {
            return title;
        }
    } public static class Report extends Document {
        private String author;
        public Report(String title, String author) {
            this(author);
            // first, so super is delegated
            System.out.println("  Report author set: " + this.author);
        } public Report(String author) {
            super(REPORT_TITLE);
            // the parent call happens here
            setAuthor(author);
        } public void setAuthor(String author) {
            this.author = author;
        } public String getAuthor() {
            return author;
        }
    } public static void main(String[] args) {
        // EXECUTION ORDER, printed by each constructor as it runs
        System.out.println("1) three level chain");
        Square square = new Square(SQUARE_NAME);
        System.out.println("   name: " + square.getName() + "  side: " + square.getSide());
        System.out.println();
        System.out.println("2) an override called from the parent constructor");
        Car car = new Car("minibus");
        System.out.println("   the same override, now that Car is ready:");
        car.describe();
        System.out.println();
        System.out.println("3) this() in one constructor, super() in another");
        Report report = new Report("Q3", "Ada");
        System.out.println("   title:  " + report.getTitle());
        System.out.println("   author: " + report.getAuthor());
        System.out.println();
        System.out.println("4) defaults live in the canonical constructor only");
        System.out.println("   role:   " + DEFAULT_ROLE);
        System.out.println("   active: " + DEFAULT_ACTIVE);
        /*
            ACTUAL OUTPUT:

                1) three level chain
                  Shape built: square
                  Square built: side 10.0
                   name: square  side: 10.0

                2) an override called from the parent constructor
                  Car describes minibus doors=0 assembled=false
                  Vehicle built: minibus
                   the same override, now that Car is ready:
                  Car describes minibus doors=4 assembled=true

                3) this() in one constructor, super() in another
                  Document built: report
                  Report author set: Ada
                   title:  report
                   author: Ada

                4) defaults live in the canonical constructor only
                   role:   guest
                   active: true

            THE FIVE RULES THAT MATTER MOST
            1) this(...) AND super(...) MUST EACH BE THE FIRST STATEMENT,
               so a single constructor may contain only one of them. Use a
               helper method when the work does not fit before the call.
            2) THE PARENT ALWAYS COMPLETES FIRST. No arrangement of the
               source can make a subclass body run before the parent
               constructor body has finished.
            3) super(...) RUNS A WHOLE CONSTRUCTOR, not just an
               assignment, so an entire chain of ancestors may execute
               before your first statement.
            4) OMITTING BOTH IS FINE, since the compiler inserts an
               implicit super(). It fails at compile time only if the
               parent has no no-argument constructor.
            5) A METHOD CALLED FROM A CONSTRUCTOR DISPATCHES TO THE
               OVERRIDE, which is why step 2 prints doors=0. Initialise
               from a factory method when that early call is needed.

            THE FIVE PHASES, IN ORDER
            MEMORY IS ALLOCATED AND FIELDS TAKE TYPE DEFAULTS.
            THE SUPER CALL IS SATISFIED, ENTERING THE PARENT.
            PARENT FIELD INITIALISERS RUN, THEN THE PARENT BODY.
            SUBCLASS FIELD INITIALISERS RUN.
            THE SUBCLASS CONSTRUCTOR BODY RUNS.
        */
    }
}

Common Java Technical Interview Questions & Answers

Interview Prep
Q1: What exactly does the compiler insert when a constructor contains neither this nor super?\nA1: A call to the parent no-argument constructor, placed at the start of the constructor body. This is silent and succeeds only if the direct parent declares a no-argument constructor; otherwise it fails at compile time rather than at runtime, which makes the omission safe to rely on.\nQ2: Why can this and super not both appear in the same constructor?\nA2: Because each must occupy the single first-statement position, and a constructor has exactly one first statement. To delegate to a sibling constructor while still initialising the parent, let the target constructor perform the super call and move extra work into a helper method.\nQ3: In what order do chained constructors actually execute?\nA3: From the top of the hierarchy downward. Every parent constructor, including its field initialisers and any further chaining, completes first, then subclass field initialisers run, and finally the subclass constructor body executes. This order is fixed and cannot be changed by rearranging the source.\nQ4: Why can a parent constructor appear to observe unset subclass state?\nA4: Because method dispatch is dynamic, so a method the parent calls may be the subclass override, which runs before subclass field initialisers. The override therefore reads type defaults such as zero or false. Such methods should be private, static, or final, or the object should be initialised from a factory method.\nQ5: Is super limited to the direct parent class?\nA5: Yes. Java supports single inheritance, so super always refers to the immediate superclass and never reaches a grandparent. A grandparent is entered only when the parent itself chains upward, and interfaces are never reached through super.\nQ6: How is this as a constructor call distinguished from this as an object reference?\nA6: By position. Followed by an opening parenthesis, this is a constructor delegation and must be the first statement. In every other position, such as this.field or this.method, it refers to the current object.\nQ7: What is the practical benefit of chaining with this?\nA7: It removes duplicated assignment logic across overloaded constructors. One canonical constructor holds all the real work, and the shorter overloads supply defaults and delegate, so adding a field means editing a single constructor rather than several.\nQ8: Why can a record constructor not call super?\nA8: Because the compiler already generates a canonical constructor that invokes the parent no-argument constructor. The compact constructor form omits the parameter list precisely so that this call cannot be duplicated, and explicit chaining is therefore rejected.

Key Takeaways, Best Practices & Clean Code Rules

Java Best Practice & Production Rules

Centralise real assignment logic in one canonical constructor.\nLet shorter overloads delegate with this rather than repeating logic.\nKeep every super call as the first statement, with nothing before it.\nNever call an overridable method from a constructor.\nMark constructor-time helper methods private, static, or final.\nPrefer a static factory method when validation must precede construction.\nInitialise subclass fields knowing the parent body already ran.\nGive every parent a no-argument constructor only if subclasses truly need one.\nOtherwise declare explicit constructors and chain with super deliberately.\nAvoid logging from constructors, since output order then surprises readers.\nDo not assume this and super can both appear, even in different branches.\nRemember that super invokes a constructor, not merely a field assignment.\nKeep constructor bodies small and move logic into named methods.\nAvoid deep hierarchies, since each level adds an unavoidable frame.\nDocument constructor side effects when a class is part of a public API.\nTreat implicit super as a real dependency on the parent no-arg constructor.\nVerify that defaults live in one place rather than scattered across overloads.
We value your privacy & transparency

OperateTools uses cookies and local storage to ensure basic tool functionality, preserve preferences, and analyze aggregated traffic. We never sell your personal data or index your document files. Learn more in our Privacy Policy.