00:00

Constructors in Java – Types, Rules and Examples

A constructor is a special block of code that runs when an object is created with new. Its job is to put the new object into a valid, ready-to-use state: set its fields, check the input, and prepare anything else the object needs.

This tutorial explains how constructors work, the different types (default, no-argument, parameterized), overloading and validation, the order in which objects are initialised, and how constructors differ from ordinary methods.

1. What Is a Constructor?

Think of a constructor as the setup step when you buy a new phone: choose the language, sign in, set the time. After that, the phone is ready. Every new Book(...) call runs the Book constructor in the same way.

A constructor:

  • Has the same name as the class.
  • Has no return type, not even void.
  • Runs automatically once, when the object is created.
  • Can take parameters and can be overloaded.
  • Can have access modifiers (public, private…) but cannot be static, final or abstract.

2. A Parameterized Constructor

ConstructorBasics.java
public class ConstructorBasics {
    static class Book {
        String title;
        String author;
        double price;

        // Parameterized constructor: same name as the class, no return type
        Book(String title, String author, double price) {
            this.title = title;
            this.author = author;
            this.price = price;
        }

        String describe() { return title + " by " + author + " (Rs. " + price + ")"; }
    }

    public static void main(String[] args) {
        Book b1 = new Book("Wings of Fire", "A. P. J. Abdul Kalam", 299);
        Book b2 = new Book("The Guide", "R. K. Narayan", 250);
        System.out.println(b1.describe());
        System.out.println(b2.describe());
    }
}
Output
Wings of Fire by A. P. J. Abdul Kalam (Rs. 299.0)
The Guide by R. K. Narayan (Rs. 250.0)

Inside the constructor, this.title refers to the field and title to the parameter. Using this. resolves the name clash.

3. Default and No-Argument Constructors

If a class declares no constructor at all, the compiler adds a default constructor: public (or matching the class's access), with no parameters and an empty body. Fields then keep their default values. You can also write your own no-argument constructor to set better starting values:

DefaultConstructor.java
public class DefaultConstructor {
    // No constructor written: the compiler adds "Counter() { }"
    static class Counter {
        int count;              // default value 0
        String label;           // default value null
    }

    // A no-argument constructor that sets useful starting values
    static class Settings {
        String theme;
        int fontSize;
        Settings() {
            theme = "light";
            fontSize = 14;
        }
    }

    public static void main(String[] args) {
        Counter c = new Counter();
        System.out.println("Counter: count=" + c.count + ", label=" + c.label);

        Settings s = new Settings();
        System.out.println("Settings: theme=" + s.theme + ", fontSize=" + s.fontSize);
    }
}
Output
Counter: count=0, label=null
Settings: theme=light, fontSize=14
Important: as soon as you write any constructor, the compiler no longer adds the default one. If Book only has Book(String, String, double), then new Book() does not compile.

4. Types of Constructors

TypeDescriptionExample
DefaultAdded by the compiler when no constructor is written(invisible) Counter() { }
No-argumentWritten by you, takes no parametersSettings() { theme = "light"; }
ParameterizedTakes values to initialise the objectBook(String title, ...)
Copy constructorCreates an object from another object of the same classBook(Book other)
Private constructorPrevents creation from outside the classprivate Config() { }

5. Constructor Overloading and this(...)

A class can have several constructors with different parameter lists. To avoid repeating code, simpler constructors call a more complete one with this(...), which must be the first statement. This is called constructor chaining.

OverloadedConstructors.java
public class OverloadedConstructors {
    static class Pizza {
        final String size;
        final String crust;
        final boolean extraCheese;

        Pizza() { this("medium"); }                                   // defaults
        Pizza(String size) { this(size, "thin", false); }
        Pizza(String size, String crust, boolean extraCheese) {      // the "main" constructor
            this.size = size;
            this.crust = crust;
            this.extraCheese = extraCheese;
        }

        @Override public String toString() {
            return size + " " + crust + "-crust pizza" + (extraCheese ? " with extra cheese" : "");
        }
    }

    public static void main(String[] args) {
        System.out.println(new Pizza());
        System.out.println(new Pizza("large"));
        System.out.println(new Pizza("small", "pan", true));
    }
}
Output
medium thin-crust pizza
large thin-crust pizza
small pan-crust pizza with extra cheese

6. Validating Input in Constructors

A constructor is the best place to reject invalid data. If the arguments are wrong, throw an exception and the object is never created, so the rest of your program never sees a half-valid object:

ValidatingConstructor.java
public class ValidatingConstructor {
    static class Account {
        private final String id;
        private double balance;

        Account(String id, double openingBalance) {
            if (id == null || id.isBlank()) throw new IllegalArgumentException("id is required");
            if (openingBalance < 0) throw new IllegalArgumentException("balance cannot be negative");
            this.id = id;
            this.balance = openingBalance;
        }

        @Override public String toString() { return id + ": " + balance; }
    }

    public static void main(String[] args) {
        System.out.println(new Account("ACC-1", 500));
        try {
            new Account("ACC-2", -10);
        } catch (IllegalArgumentException e) {
            System.out.println("Not created: " + e.getMessage());
        }
    }
}
Output
ACC-1: 500.0
Not created: balance cannot be negative

7. Initialization Order

When new Car() runs, Java performs these steps in a fixed order:

ConstructorOrder.java
public class ConstructorOrder {
    static class Vehicle {
        Vehicle() { System.out.println("1. Vehicle constructor"); }
    }

    static class Car extends Vehicle {
        String model = initModel();             // field initializers run after super()

        { System.out.println("3. Car instance initializer block"); }

        Car() {
            super();                            // always first (added automatically if omitted)
            System.out.println("4. Car constructor body, model = " + model);
        }

        static String initModel() {
            System.out.println("2. Car field initializer");
            return "Nexon";
        }
    }

    public static void main(String[] args) {
        new Car();
    }
}
Output
1. Vehicle constructor
2. Car field initializer
3. Car instance initializer block
4. Car constructor body, model = Nexon
  1. Memory is allocated and all fields get default values.
  2. The parent constructor runs (super(), added automatically if you do not write it).
  3. Field initializers and instance initializer blocks run, in the order they appear in the class.
  4. The rest of the constructor body runs.

Static fields and static blocks run earlier, once, when the class is first loaded.

8. Constructor vs Method

ConstructorMethod
Same name as the classAny name
No return typeMust have a return type or void
Called automatically by newCalled explicitly, any number of times
Runs once per objectCan run many times
Not inheritedInherited (unless private)
Cannot be static, final or abstractCan be

9. Constructors in Records

A record gets a canonical constructor automatically. You can add a compact constructor to validate the values without repeating the assignments:

Compact constructor
record Temperature(double celsius) {
    Temperature {
        if (celsius < -273.15) throw new IllegalArgumentException("below absolute zero");
    }
}

10. Best Practices

  • Leave every object fully initialised and valid when the constructor finishes.
  • Validate arguments and fail fast with clear exceptions.
  • Keep constructors simple: no heavy work, network calls or long computations.
  • Do not call overridable methods from a constructor; the subclass is not ready yet.
  • Use this(...) to avoid duplicated code between overloaded constructors.
  • With many optional parameters, consider a builder or static factory methods.

11. Summary

  • A constructor initialises a new object; it has the class's name and no return type.
  • The compiler adds a default constructor only when you write none.
  • Constructors can be overloaded and can call each other with this(...).
  • The parent constructor always runs first, then field initializers, then the body.
  • Validate input in constructors so invalid objects are never created.

Related Tutorials

Reference: Oracle Java Tutorials: Providing Constructors for Your Classes