Calling Another Constructor

Introduction

Constructor chaining is calling one constructor from another constructor of the same class using this() or from parent class using super().


Using this()

Syntax:

class ClassName {
    ClassName() {
        this(arguments);  // Call another constructor
    }

    ClassName(parameters) {
        // Code
    }
}

Important: this() must be the first statement in constructor.


Simple Example

class Student {
    String name;
    int rollNo;
    double marks;

    // Constructor 1: No parameters
    Student() {
        this("Unknown", 0, 0.0);  // Call constructor 3
    }

    // Constructor 2: Two parameters
    Student(String name, int rollNo) {
        this(name, rollNo, 0.0);  // Call constructor 3
    }

    // Constructor 3: All parameters (main constructor)
    Student(String name, int rollNo, double marks) {
        this.name = name;
        this.rollNo = rollNo;
        this.marks = marks;
    }

    void display() {
        System.out.println(name + ", " + rollNo + ", " + marks);
    }
}

public class Main {
    public static void main(String[] args) {
        Student s1 = new Student();
        Student s2 = new Student("John", 101);
        Student s3 = new Student("Alice", 102, 85.5);

        s1.display();  // Unknown, 0, 0.0
        s2.display();  // John, 101, 0.0
        s3.display();  // Alice, 102, 85.5
    }
}

Why Use Constructor Chaining?

  1. Code Reuse: Avoid duplicate code
  2. Maintainability: Change logic in one place
  3. Consistency: Same initialization logic
  4. Flexibility: Multiple ways to create objects

Rules for this()

  1. Must be first statement
  2. Cannot use both this() and super() in same constructor
  3. Cannot be used in regular methods
  4. Cannot call itself (no recursion)

Complete Example

class Rectangle {
    double length;
    double width;

    // Constructor 1: Square (one side)
    Rectangle(double side) {
        this(side, side);  // Call constructor 2
    }

    // Constructor 2: Rectangle (length and width)
    Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }

    double area() {
        return length * width;
    }

    void display() {
        System.out.println("Length: " + length);
        System.out.println("Width: " + width);
        System.out.println("Area: " + area());
        System.out.println();
    }
}

public class Main {
    public static void main(String[] args) {
        Rectangle square = new Rectangle(5);      // 5x5 square
        Rectangle rect = new Rectangle(4, 6);     // 4x6 rectangle

        square.display();
        rect.display();
    }
}

Chain Pattern

class BankAccount {
    String accountNumber;
    String holderName;
    double balance;
    String accountType;

    // Constructor 1: Only essential info
    BankAccount(String accountNumber, String holderName) {
        this(accountNumber, holderName, 0.0);  // Call constructor 2
    }

    // Constructor 2: With initial balance
    BankAccount(String accountNumber, String holderName, double balance) {
        this(accountNumber, holderName, balance, "Savings");  // Call constructor 3
    }

    // Constructor 3: Full details (main constructor)
    BankAccount(String accountNumber, String holderName,
                double balance, String accountType) {
        this.accountNumber = accountNumber;
        this.holderName = holderName;
        this.balance = balance;
        this.accountType = accountType;
        System.out.println("Account created: " + accountType);
    }
}

With Default Values

class Product {
    String name;
    double price;
    int quantity;
    String category;

    // Default constructor
    Product() {
        this("Unknown", 0.0, 0, "General");
    }

    // Name and price only
    Product(String name, double price) {
        this(name, price, 0, "General");
    }

    // Full constructor
    Product(String name, double price, int quantity, String category) {
        this.name = name;
        this.price = price;
        this.quantity = quantity;
        this.category = category;
    }

    void display() {
        System.out.println(name + ", " + price + ", " + quantity + ", " + category);
    }
}

public class Main {
    public static void main(String[] args) {
        Product p1 = new Product();
        Product p2 = new Product("Laptop", 50000);
        Product p3 = new Product("Mouse", 500, 10, "Electronics");

        p1.display();  // Unknown, 0.0, 0, General
        p2.display();  // Laptop, 50000.0, 0, General
        p3.display();  // Mouse, 500.0, 10, Electronics
    }
}

this() vs super()

this()super()
Calls constructor of same classCalls constructor of parent class
Used for constructor chainingUsed for inheritance
this(args)super(args)
Must be first statementMust be first statement
Cannot use both in same constructorCannot use both in same constructor

Common Mistakes

Mistake 1: Not First Statement

// ❌ Wrong
class Wrong {
    int x;

    Wrong() {
        x = 10;           // Other code first
        this(20);         // Error: must be first
    }

    Wrong(int x) {
        this.x = x;
    }
}

// ✓ Correct
class Correct {
    int x;

    Correct() {
        this(10);         // First statement
    }

    Correct(int x) {
        this.x = x;
    }
}

Mistake 2: Using Both this() and super()

// ❌ Wrong
class Wrong extends Parent {
    Wrong() {
        super();          // Error: Cannot use both
        this(10);
    }

    Wrong(int x) {
        // Code
    }
}

Mistake 3: Circular Call

// ❌ Wrong
class Wrong {
    Wrong() {
        this(10);         // Calls Wrong(int)
    }

    Wrong(int x) {
        this();           // Calls Wrong() - Infinite loop!
    }
}

Practical Example

class Employee {
    String employeeId;
    String name;
    String department;
    double salary;
    String designation;

    // New employee (trainee)
    Employee(String employeeId, String name) {
        this(employeeId, name, "Training", 20000, "Trainee");
    }

    // Employee with department
    Employee(String employeeId, String name, String department) {
        this(employeeId, name, department, 30000, "Junior");
    }

    // Employee with department and salary
    Employee(String employeeId, String name, String department, double salary) {
        this(employeeId, name, department, salary, "Senior");
    }

    // Full constructor
    Employee(String employeeId, String name, String department,
             double salary, String designation) {
        this.employeeId = employeeId;
        this.name = name;
        this.department = department;
        this.salary = salary;
        this.designation = designation;
    }

    void display() {
        System.out.println("ID: " + employeeId);
        System.out.println("Name: " + name);
        System.out.println("Department: " + department);
        System.out.println("Salary: " + salary);
        System.out.println("Designation: " + designation);
        System.out.println();
    }
}

public class Main {
    public static void main(String[] args) {
        Employee e1 = new Employee("E001", "John");
        Employee e2 = new Employee("E002", "Alice", "IT");
        Employee e3 = new Employee("E003", "Bob", "HR", 50000);
        Employee e4 = new Employee("E004", "Carol", "IT", 80000, "Manager");

        e1.display();
        e2.display();
        e3.display();
        e4.display();
    }
}

Constructor Execution Flow

class Flow {
    Flow() {
        this(10);                           // 1. Call this
        System.out.println("No-arg");       // 4. Execute after parameterized
    }

    Flow(int x) {
        System.out.println("Param: " + x);  // 2. Execute first
    }                                       // 3. Return to calling constructor
}

public class Main {
    public static void main(String[] args) {
        Flow f = new Flow();
        // Output:
        // Param: 10
        // No-arg
    }
}

Quick Reference

class Example {
    int x, y;

    // Constructor 1
    Example() {
        this(0, 0);        // Call constructor 3
    }

    // Constructor 2
    Example(int x) {
        this(x, x);        // Call constructor 3
    }

    // Constructor 3 (main)
    Example(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

// Usage
Example e1 = new Example();      // 0, 0
Example e2 = new Example(5);     // 5, 5
Example e3 = new Example(3, 7);  // 3, 7

Exam Tips

Remember:

  1. Use this() to call another constructor
  2. Must be first statement
  3. Cannot use both this() and super()
  4. Used for constructor chaining
  5. Reduces code duplication
  6. Improves maintainability
  7. Cannot call from regular methods
  8. No circular calls
  9. Called constructor executes first
  10. Good for default values

Common Questions:

  • What is constructor chaining?
  • How to call another constructor?
  • Rules for this()?
  • this() vs super()?
  • Where must this() be placed?
  • Can we use both this() and super()?
  • Benefits of constructor chaining?
  • Common mistakes?