Java Constructor Chaining: Learn this() and super() with Examples

0

Imagine a class that offers several ways to create an object. One constructor may provide default values, another may accept a name, and another may accept a name plus an age. If every constructor contains its own initialization logic, the same code can quickly become duplicated and difficult to maintain.

Constructor chaining solves this problem. It allows one constructor to call another constructor so that object initialization can follow a single, organized path.

What Is Constructor Chaining?

Constructor chaining is the process of one constructor calling another constructor of the same class or a constructor of its parent class.

There are two forms you should recognize:

  • Calling another constructor in the same class using this().
  • Calling a constructor of the parent class using super().

In this chapter, the main focus is constructor chaining within the same class. The this() constructor call is especially important because it lets overloaded constructors reuse initialization logic instead of duplicating it.

Why Do We Need Constructor Chaining?

Suppose a class has three constructors and all three need to initialize the same fields. Without chaining, you may repeat the same statements in every constructor.

class Employee {

    String name;
    int age;
    String department;

    Employee() {
        name = "Unknown";
        age = 0;
        department = "General";
    }

    Employee(String name) {
        this.name = name;
        age = 0;
        department = "General";
    }

    Employee(String name, int age) {
        this.name = name;
        this.age = age;
        department = "General";
    }

}

The code works, but notice the repetition. The default age and department are assigned in multiple constructors. If the default department later changes from "General" to "Engineering", several constructors may need modification.

Constructor chaining gives us a cleaner solution: let one constructor perform the common initialization and let the other constructors delegate to it.

Basic Constructor Chaining with this()

The this() syntax calls another constructor in the same class.

class Employee {

    String name;
    int age;
    String department;

    Employee() {
        this("Unknown", 0, "General");
    }

    Employee(String name) {
        this(name, 0, "General");
    }

    Employee(String name, int age) {
        this(name, age, "General");
    }

    Employee(String name, int age, String department) {
        this.name = name;
        this.age = age;
        this.department = department;
    }

}

Now the actual field initialization happens in one place: the constructor that accepts all three values. The other constructors simply delegate to it.

This design is easier to maintain because the initialization logic has a single source of truth.

How the Chain Works

Consider the following statement:

Employee employee = new Employee();

The no-argument constructor executes first and calls another constructor using this("Unknown", 0, "General").

Employee()
    ↓
Employee(String, int, String)
    ↓
Object Initialized

The constructor receiving all three values performs the actual field initialization. Control then returns through the constructor chain.

Another Example

Let's use a simple Student class to make the idea more concrete.

class Student {

    String name;
    int age;
    String course;

    Student() {
        this("Unknown");
    }

    Student(String name) {
        this(name, 18);
    }

    Student(String name, int age) {
        this(name, age, "Java");
    }

    Student(String name, int age, String course) {
        this.name = name;
        this.age = age;
        this.course = course;
    }

}

Now the constructors form a chain:

Student()
    ↓
Student(String)
    ↓
Student(String, int)
    ↓
Student(String, int, String)

Each constructor adds more information until the final constructor has everything required to initialize the object.

Creating Objects Through Different Constructors

public class Main {

    public static void main(String[] args) {

        Student s1 = new Student();
        Student s2 = new Student("Rahul");
        Student s3 = new Student("Anita", 21);
        Student s4 = new Student("Vikram", 22, "Python");

        System.out.println(s1.name + " " + s1.age + " " + s1.course);
        System.out.println(s2.name + " " + s2.age + " " + s2.course);
        System.out.println(s3.name + " " + s3.age + " " + s3.course);
        System.out.println(s4.name + " " + s4.age + " " + s4.course);

    }

}
Unknown 18 Java
Rahul 18 Java
Anita 21 Java
Vikram 22 Python

The different constructors provide different entry points, but the final initialization logic remains centralized.

this() Must Be the First Statement

There is a strict rule associated with the this() constructor call: it must be the first statement inside the constructor.

class Student {

    Student() {

        System.out.println("Starting");
        this("Unknown");

    }

    Student(String name) {
        System.out.println(name);
    }

}

This code is invalid because the this() call appears after another statement.

The correct structure is:

class Student {

    Student() {
        this("Unknown");
    }

    Student(String name) {
        System.out.println(name);
    }

}

Important: A constructor can use this() to delegate initialization, but that call must appear as the first statement in the constructor.

this() and this Are Different

This is a small syntax difference with a very important meaning.

Syntax Purpose
this Refers to the current object
this() Calls another constructor in the same class

For example, this.name refers to an instance variable of the current object, while this() invokes another constructor.

Constructor Chaining Reduces Duplication

One of the strongest reasons to use constructor chaining is to avoid repeating initialization code.

class Product {

    String name;
    double price;
    String category;

    Product() {
        this("Unknown", 0.0, "General");
    }

    Product(String name, double price) {
        this(name, price, "General");
    }

    Product(String name, double price, String category) {
        this.name = name;
        this.price = price;
        this.category = category;
    }

}

Suppose the default category changes later. With constructor chaining, you can update the relevant delegated call rather than searching through several constructors for duplicated initialization statements.

Constructor Chaining Is Not Recursion

Constructor chaining may look like constructors are repeatedly calling one another, but the chain must eventually reach a constructor that performs the initialization. If constructors keep calling each other indefinitely, Java detects the circular dependency during compilation.

class Test {

    Test() {
        this(10);
    }

    Test(int value) {
        this();
    }

}

This creates a circular constructor invocation: the no-argument constructor calls the integer constructor, which calls the no-argument constructor again. Java rejects this design.

Remember: A constructor chain must eventually terminate at a constructor that performs the actual initialization. Never create a circular chain.

Constructor Chaining and super()

Constructor chaining can also involve inheritance. A constructor can invoke a constructor in its parent class using super(). This is different from this(), which targets another constructor in the same class.

Call Calls
this() Another constructor in the same class
super() A constructor in the parent class

Understanding this distinction is essential before moving into inheritance and constructor execution order.

Common Beginner Mistakes

Putting Code Before this()

Student() {
    System.out.println("Hello");
    this("Unknown");
}

The this() call must be the first statement.

Calling the Wrong Constructor

class Student {

    Student() {
        this("Rahul", 20);
    }

    Student(String name) {
    }

}

The call requests a constructor with String and int parameters, but no such constructor exists.

Creating a Circular Chain

If constructor A calls constructor B and constructor B calls constructor A, the chain can never reach a final initialization constructor. Java reports a compilation error.

Best Practices

  • Use constructor chaining to centralize common initialization logic.
  • Make the most complete constructor responsible for the actual field initialization when appropriate.
  • Keep constructor chains simple enough that their flow remains easy to understand.
  • Avoid circular constructor invocation.
  • Use this() for same-class constructor delegation and super() for parent-class constructor invocation.

Interview Insight

A common interview question is: Can this() and super() be used together in the same constructor? No. Both constructor calls must be the first statement, so they cannot both appear in the same constructor.

Another popular question is: Why is constructor chaining useful? The strongest answer is that it promotes code reuse, reduces duplicated initialization logic, and makes overloaded constructors easier to maintain.

Quick Revision

Concept Key Point
Constructor Chaining One constructor calls another constructor
this() Calls another constructor in the same class
super() Calls a parent-class constructor
Position this() must be the first statement
Benefit Reduces duplicated initialization code
Restriction Circular constructor calls are not allowed

Final Thoughts

Constructor chaining gives overloaded constructors a clear relationship instead of turning them into isolated blocks of repeated code. By using this() intelligently, you can let simpler constructors delegate to more complete ones and keep object initialization in one reliable place. Once this pattern becomes familiar, constructor design in larger Java classes becomes much cleaner and easier to maintain.

Post a Comment

0Comments
Post a Comment (0)