Mastering Java Constructor Overloading with Examples

Mastering Java Constructor Overloading with Examples


In this beginners-friendly guide, you will learn Java constructor overloading with examples. We will explain what constructor overloading is, why it is useful for students and new Java learners, how to write multiple constructors in one class, and the rules to avoid common mistakes. You will also see simple Java constructor examples, output, and a real-life use case. If you are just starting with Java, this page is part of our Java constructors tutorial under the CodDesire Java series. For more topics, visit our Java section.

Key takeaways: Java constructor overloading with examples

  • Overloading lets a class have multiple constructors that differ by parameter list (number, types, order).
  • The compiler selects the matching constructor at compile time based on the arguments you pass.
  • Prefer one validated “full” constructor and delegate from simpler ones using this(...) for clean, centralized initialization.

What is constructor overloading in Java?

Java constructor overloading with examples shown via a Student class and object creation paths
One class, many ways to construct: default, single-arg, and multi-arg constructor ideas.

Constructor overloading in Java means a class can have more than one constructor, but each must have a different parameter list (number, types, and/or order of parameters). The compiler decides which constructor to call at compile time based on the arguments you pass.

In simple terms: it lets you create objects in different ways. For example, you might create a Box with no size, a Box with one size (a cube), or a Box with width, height, and depth.

Basic syntax reminder

  • A constructor has the same name as the class.
  • It has no return type (not even void).
  • Constructors can be overloaded by changing their parameter lists.

Simple Java constructor examples (Box)

Code
class Box {
    int width, height, depth;

    // Default (no-arg) constructor
    Box() {
        this(1, 1, 1); // delegate to the 3-arg constructor
    }

    // One-parameter (cube) constructor
    Box(int size) {
        this(size, size, size);
    }

    // Parameterized constructor
    Box(int width, int height, int depth) {
        this.width = width;
        this.height = height;
        this.depth = depth;
    }

    int volume() {
        return width * height * depth;
    }

    class="cd-keyword cd-access">public static void main(String[] args) {
        Box a = new Box();          // 1x1x1
        Box b = new Box(5);         // 5x5x5
        Box c = new Box(2, 3, 4);   // 2x3x4

        System.out.println(a.volume());
        System.out.println(b.volume());
        System.out.println(c.volume());
    }
}
Output
1
125
24

Why use constructor overloading?

Java constructor overloading with examples: constructor chaining with this() and super()
See how this() and super() route constructor calls across overloaded and inherited constructors.
  • Convenience for callers: Create objects with different sets of available information (e.g., with or without optional data).
  • Readability: Code is easier to understand at the call site.
  • Validation in one place: Use a “full” constructor for checks and delegate from simpler constructors.
  • Backward compatibility: Add new ways to construct without breaking old code.

Default and parameterized constructors in Java

By default, if you do not write any constructor in a class, Java provides a compiler-generated no-argument constructor that simply calls the superclass constructor. But if you declare any constructor yourself, the default one is not generated.

Type When it exists What it does
Default (no-arg) Only if you declare no constructors at all Initializes fields to default values (0, false, null), calls super()
Parameterized Whenever you write it Initializes fields using the provided arguments; often does validation

How to overload a constructor in Java step by step

  1. Decide which sets of data you want to allow for object creation (e.g., name only, name + age).
  2. Create a full constructor that takes all required fields and does validation.
  3. Write simpler constructors that call the full one using this(...) and pass default values as needed.
  4. Test each constructor by creating objects and printing results.
Design flow for overloaded constructors
1) Identify required and optional fields
2) Implement the full constructor (all fields)
3) Validate inputs inside the full constructor
4) Add simpler constructors that delegate with this(...)
5) Test each overload with example calls

Java constructor overloading example program for students (Student)

Code
class Student {
    String name;
    int age;
    String grade;

    // 1) No-arg: default values
    Student() {
        this("Unknown", 0, "NA");
    }

    // 2) One-arg: name only
    Student(String name) {
        this(name, 0, "NA");
    }

    // 3) Two-arg: name + age
    Student(String name, int age) {
        this(name, age, "NA");
    }

    // 4) Three-arg: full constructor (centralized initialization)
    Student(String name, int age, String grade) {
        if (name == null || name.isBlank()) {
            throw new IllegalArgumentException("Name must not be blank");
        }
        if (age < 0) {
            throw new IllegalArgumentException("Age must be non-negative");
        }
        this.name = name;
        this.age = age;
        this.grade = grade;
    }

    void print() {
        System.out.println(name + " (" + age + ") - " + grade);
    }

    class="cd-keyword cd-access">public static void main(String[] args) {
        new Student().print();
        new Student("Ava").print();
        new Student("Ben", 19).print();
        new Student("Chin", 20, "A").print();
    }
}
Output
Unknown (0) - NA
Ava (0) - NA
Ben (19) - NA
Chin (20) - A

Constructor chaining: this(…), super(…), and Java 25+ flexible bodies

Constructors can call other constructors:

  • this(...) calls another constructor in the same class (commonly used to delegate to the “full” constructor).
  • super(...) calls a constructor in the superclass.

In Java 25 and later, the language allows certain statements to appear before this(...) or super(...). This is known as “flexible constructor bodies” and is useful for safe pre-validation or computing values before you delegate. You still cannot use the not-yet-initialized this (for example, calling an instance method) in that prologue.

Aspect this(…) super(…)
Purpose Delegate to another constructor in the same class (common for overloads) Invoke a specific constructor in the superclass
Position in constructor Traditionally first; Java 25+ allows limited statements before it Traditionally first; Java 25+ allows limited statements before it
When required Optional; use to centralize initialization Implicit no-arg super() is inserted if none specified and available
Common mistake Calling instance methods or using fields before delegation in Java 25+ prologue Forgetting to call a non-existent no-arg super when superclass has no no-arg constructor
Example this(name, age, "NA"); super(len);

Example: pre-validation before calling super (Java 25+)

Code
class Base {
    Base(int x) {
        System.out.println("Base with x = " + x);
    }
}

class Sub extends Base {
    Sub(String text) {
        // Java 25+: allowed before super(...)
        int len = (text == null) ? 0 : text.trim().length();
        super(len);
    }

    class="cd-keyword cd-access">public static void main(String[] args) {
        new Sub(" hello ");
    }
}
Output
Base with x = 7

If you are using Java versions before 25, put super(...) or this(...) as the very first statement in the constructor.

Constructor overloading rules in Java

  • Constructors are distinguished only by their parameter lists (number, types, order). Return type does not apply to constructors.
  • Throws clauses and generic type parameters do not differentiate overloads.
  • Overload resolution follows the same compile-time rules as method overloading: the most specific applicable constructor is chosen; ambiguity is a compile-time error.
  • Varargs (...) is considered after fixed-arity matches.
  • Constructors are not inherited and cannot be overridden.
  • If you write any constructor, Java will not generate a default no-arg constructor for you.

Ambiguity example

Code
class Printer {
    Printer(String s) { System.out.println("String"); }
    Printer(StringBuilder sb) { System.out.println("StringBuilder"); }

    class="cd-keyword cd-access">public static void main(String[] args) {
        // new Printer(null); // Compile-time error: reference to Printer is ambiguous
        new Printer("hi");          // OK - calls Printer(String)
        new Printer(new StringBuilder("x")); // OK - calls Printer(StringBuilder)
    }
}

Varargs vs fixed-arity selection

Code
class Reporter {
    Reporter(String tag) {
        System.out.println("Fixed-arity: one String");
    }
    Reporter(String... tags) {
        System.out.println("Varargs: many Strings");
    }

    class="cd-keyword cd-access">public static void main(String[] args) {
        new Reporter("debug");       // chooses the fixed-arity constructor
        new Reporter("a", "b");      // chooses the varargs constructor
    }
}
Output
Fixed-arity: one String
Varargs: many Strings

Constructor overloading in Java with real life example

Imagine opening a bank account with minimum information at first, but also allowing a richer constructor later.

Code
class BankAccount {
    String owner;
    double balance;
    String type;

    // Minimal: owner only
    BankAccount(String owner) {
        this(owner, 0.0, "SAVINGS");
    }

    // Owner + initial deposit
    BankAccount(String owner, double initialDeposit) {
        this(owner, initialDeposit, "SAVINGS");
    }

    // Full constructor with validation
    BankAccount(String owner, double initialDeposit, String type) {
        if (owner == null || owner.isBlank()) {
            throw new IllegalArgumentException("Owner is required");
        }
        if (initialDeposit < 0) {
            throw new IllegalArgumentException("Initial deposit must be non-negative");
        }
        this.owner = owner;
        this.balance = initialDeposit;
        this.type = type;
    }

    void print() {
        System.out.println(owner + " | " + type + " | " + balance);
    }

    class="cd-keyword cd-access">public static void main(String[] args) {
        new BankAccount("Riya").print();
        new BankAccount("Sam", 1000).print();
        new BankAccount("Lee", 500, "CURRENT").print();
    }
}
Output
Riya | SAVINGS | 0.0
Sam | SAVINGS | 1000.0
Lee | CURRENT | 500.0

Records and constructors (modern Java)

Java records provide a canonical constructor that matches their components, and you can write a compact constructor for validation. Any extra constructors must delegate to the canonical one using this(...).

Code
record Point(int x, int y) {
    // Compact canonical constructor: validate inputs
    class="cd-keyword cd-access">public Point {
        if (x < 0 || y < 0) {
            throw new IllegalArgumentException("Coordinates must be non-negative");
        }
    }
    // Additional overloaded constructor
    class="cd-keyword cd-access">public Point(int both) {
        this(both, both); // must delegate to the canonical constructor
    }
}

Common mistakes when overloading constructors in Java

  • Thinking a default no-arg constructor always exists. It exists only if you did not write any constructor.
  • Changing only the throws clause or generic type parameters—these do not create a new overload.
  • Assuming return type matters—constructors have no return type.
  • Calling instance methods or using this in the pre-delegation prologue (Java 25+ restriction). Perform only safe computations there.
  • Creating too many overloads (telescoping). Consider a builder or static factory for many optional fields.
  • Ignoring ambiguity with null for unrelated reference types (e.g., String vs StringBuilder).

FAQ: Beginners guide to Java constructors and overloading

What is constructor overloading in Java in simple terms?

It means writing multiple constructors in the same class with different parameter lists so you can create objects in different ways. The compiler picks the right one based on the arguments.

Why do we use constructor overloading in Java?

To provide flexible ways to create an object: minimal info, partial info, or full info with validation. It makes code cleaner and easier to use.

How do I write multiple constructors in one Java class?

Create a “full” constructor that initializes all required fields and performs checks. Then add simpler constructors that call it using this(...), supplying defaults for missing values. Test each path by creating objects with different arguments.

Is constructor overloading the same as method overloading in Java?

They follow similar selection rules, but constructors are special: they have no return type, are not inherited, and cannot be overridden. Overload resolution is done at compile time in both cases.

What happens if I don’t create any constructor in Java?

The compiler provides a default no-argument constructor that calls super(). If you declare any constructor yourself, Java does not add the default one.

Summary

Constructor overloading in Java for beginners is about giving your classes multiple, clear ways to be created. Start with one validated, full constructor and delegate from simpler ones with this(...). Understand the rules (parameter lists, overload resolution, varargs) and be aware of modern features like Java 25’s flexible constructor bodies. As you practice, try building small programs and then grow to real-life models like bank accounts or shapes. For more topics and practice, continue in our Java tutorials at CodDesire.

Sources / Further reading

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted