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?
- Code Reuse: Avoid duplicate code
- Maintainability: Change logic in one place
- Consistency: Same initialization logic
- Flexibility: Multiple ways to create objects
Rules for this()
- Must be first statement
- Cannot use both
this()andsuper()in same constructor - Cannot be used in regular methods
- 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 class | Calls constructor of parent class |
| Used for constructor chaining | Used for inheritance |
this(args) | super(args) |
| Must be first statement | Must be first statement |
| Cannot use both in same constructor | Cannot 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:
- Use this() to call another constructor
- Must be first statement
- Cannot use both this() and super()
- Used for constructor chaining
- Reduces code duplication
- Improves maintainability
- Cannot call from regular methods
- No circular calls
- Called constructor executes first
- 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?