Skip to content

Java Constructors

Updated 9 min read Aimerscrew

In the last lesson, you created objects and then filled in every field by hand, one line at a time. That works, but it's easy to forget a field and end up with a half-built object. Java constructors fix this: they set up an object the moment it's created. In this lesson, you'll write default and parameterized constructors, offer several ways to build an object, and stop bad values at the door.

🌍 Real-life example

When you open a bank account, the bank doesn't hand you an empty folder and say "fill it in later". The clerk asks for your name and first deposit right away, and your account starts life complete. A constructor is that clerk: every new object goes through it before anyone can use it.

What is a constructor in Java?

A constructor is a special method-like block that runs once, automatically, when an object is created with new. It looks like a method with two differences:

  • Its name is exactly the same as the class name, including the capital letter.
  • It has no return type, not even void.
class Lamp {
    String color;

    Lamp() {               // a constructor: same name as the class, no return type
        color = "white";
    }
}

When you write new Lamp(), the parentheses are a call to this constructor. Here is how constructors compare with ordinary methods:

ConstructorMethod
NameSame as the classAny name (usually a verb)
Return typeNone, not even voidRequired (void, int, ...)
When it runsAutomatically, once, during newWhenever you call it
PurposeSet up a new objectPerform an action

The no-argument constructor

A constructor with empty parentheses is called a no-argument (or no-arg) constructor. Use it to give every new object sensible starting values:

public class DeskLamp {
    public static void main(String[] args) {
        Lamp lamp = new Lamp();   // uses the no-argument constructor
        lamp.show();
    }
}

class Lamp {
    String color;
    int brightness;
    boolean on;

    Lamp() {
        color = "white";
        brightness = 70;
        on = false;
        System.out.println("A new lamp was made!");
    }

    void show() {
        System.out.println(color + " lamp, brightness " + brightness + "%, on: " + on);
    }
}
A new lamp was made!
white lamp, brightness 70%, on: false

The message prints during new Lamp(), before show() is called. That proves the constructor runs automatically.

What is the default constructor?

In Java classes and objects, you wrote classes like Book with no constructor at all, yet new Book() still worked. That's because when a class has no constructors, Java quietly adds an empty no-arg one for you. This invisible constructor is called the default constructor. It does nothing except leave the fields at their default values (0, false, null).

class Book {
    String title;
    // Java acts as if you had written:
    // Book() { }
}

Parameterized constructors

Most of the time, each object needs different starting values. A parameterized constructor takes parameters, just like a method, and uses them to fill the fields:

public class BankDemo {
    public static void main(String[] args) {
        BankAccount maria = new BankAccount("Maria", 250.0);
        BankAccount ken = new BankAccount("Ken", 40.0);

        maria.show();
        ken.show();
    }
}

class BankAccount {
    String owner;
    double balance;

    BankAccount(String ownerName, double startingBalance) {
        owner = ownerName;
        balance = startingBalance;
    }

    void show() {
        System.out.println(owner + " has $" + balance);
    }
}
Maria has $250.0
Ken has $40.0

Compare main here with the last lesson: one line per object instead of one line per field. And because the constructor requires a name and a balance, nobody can create an account without them.

What happens when you call new?

Creating an object is a short, fixed sequence. Java reserves memory and sets every field to its default value, then runs your constructor, then hands back a reference that you store in a variable:

Animation of BankAccount maria = new BankAccount("Maria", 250.0) in three steps: 1 reserve memory with owner null and balance 0.0, 2 the constructor sets owner to Maria and balance to 250.0, 3 the reference is stored in the variable maria
Memory first, then the constructor, then the reference goes into your variable.

Constructor overloading

A class can have several constructors, as long as their parameter lists differ in number or types. This is called constructor overloading, and it works exactly like method overloading. Java picks the constructor whose parameters match the arguments you pass:

public class PizzaShop {
    public static void main(String[] args) {
        Pizza a = new Pizza();
        Pizza b = new Pizza("large");
        Pizza c = new Pizza("small", "mushrooms");

        a.show();
        b.show();
        c.show();
    }
}

class Pizza {
    String size;
    String topping;

    Pizza() {
        size = "medium";
        topping = "cheese";
    }

    Pizza(String chosenSize) {
        size = chosenSize;
        topping = "cheese";
    }

    Pizza(String chosenSize, String chosenTopping) {
        size = chosenSize;
        topping = chosenTopping;
    }

    void show() {
        System.out.println("A " + size + " pizza with " + topping);
    }
}
A medium pizza with cheese
A large pizza with cheese
A small pizza with mushrooms

Overloading gives callers a choice: order "the usual", or customize as much as they want.

Constructor chaining with this(...)

Look at the three Pizza constructors again: they repeat the same assignments. If you later add a field, you'd have to update all three. Constructor chaining fixes this. Inside a constructor, this(...) calls another constructor of the same class, so you can write the real work once and let the shorter constructors pass along default values:

public class CoffeeBar {
    public static void main(String[] args) {
        Coffee usual = new Coffee();
        Coffee big = new Coffee("large");
        Coffee custom = new Coffee("small", "oat", 2);

        usual.show();
        big.show();
        custom.show();
    }
}

class Coffee {
    String size;
    String milk;
    int shots;

    Coffee() {
        this("medium");                     // calls Coffee(String)
    }

    Coffee(String chosenSize) {
        this(chosenSize, "whole", 1);       // calls Coffee(String, String, int)
    }

    Coffee(String chosenSize, String chosenMilk, int chosenShots) {
        size = chosenSize;
        milk = chosenMilk;
        shots = chosenShots;
    }

    void show() {
        System.out.println(size + " coffee, " + milk + " milk, " + shots + " shot(s)");
    }
}
medium coffee, whole milk, 1 shot(s)
large coffee, whole milk, 1 shot(s)
small coffee, oat milk, 2 shot(s)

new Coffee() calls this("medium"), which calls this("medium", "whole", 1), which finally sets the fields. All the real assignments live in one constructor.

⚠️ Rule

this(...) must be the very first statement in a constructor, and you can use it only once there. Putting any line before it is a compile error. You'll see more uses of this in the Java this keyword.

Why does the default constructor disappear?

Here's a surprise that catches almost everyone. Java adds the invisible default constructor only if you write no constructors at all. As soon as you write any constructor, Java assumes you've taken charge and adds nothing:

class Ticket {
    String event;

    Ticket(String eventName) {
        event = eventName;
    }
}

// somewhere in main:
Ticket t = new Ticket();   // compile error!

The compiler refuses, because the only constructor needs a String:

error: constructor Ticket in class Ticket cannot be applied to given types;
        Ticket t = new Ticket();
                   ^
  required: String
  found:    no arguments

If you want both new Ticket() and new Ticket("Concert") to work, write the no-arg constructor yourself, ideally chaining it: Ticket() { this("General admission"); }.

Validating values in a constructor

A constructor is the perfect place to reject bad data, because every object must pass through it. If a value makes no sense, you can stop the program with an error instead of creating a broken object. The line throw new IllegalArgumentException(...) does exactly that. (You'll learn how throw works in Java throw and throws; for now, read it as "stop and report this problem".)

class ConcertTicket {
    String row;
    int quantity;

    ConcertTicket(String chosenRow, int chosenQuantity) {
        if (chosenQuantity < 1) {
            throw new IllegalArgumentException("quantity must be at least 1, got " + chosenQuantity);
        }
        row = chosenRow;
        quantity = chosenQuantity;
    }
}

Now new ConcertTicket("Row F", 3) works normally, but new ConcertTicket("Row G", 0) stops the program with a clear message:

Exception in thread "main" java.lang.IllegalArgumentException: quantity must be at least 1, got 0

A crash with a clear reason is far better than a ticket order for zero seats sneaking into your system.

💡 Tip

A good rule of thumb: once a constructor finishes, the object should be complete and valid. Every required field is set, and every value makes sense.

Real-world example: gym memberships

Most members sign up for the basic monthly plan, but some pick a longer premium plan. Two chained constructors handle both cases neatly:

public class Gym {
    public static void main(String[] args) {
        Membership basic = new Membership("Lena");
        Membership premium = new Membership("Omar", "premium", 12);

        basic.show();
        premium.show();
    }
}

class Membership {
    String member;
    String plan;
    int months;

    Membership(String name) {
        this(name, "basic", 1);
    }

    Membership(String name, String chosenPlan, int chosenMonths) {
        member = name;
        plan = chosenPlan;
        months = chosenMonths;
    }

    void show() {
        System.out.println(member + ": " + plan + " plan for " + months + " month(s)");
    }
}
Lena: basic plan for 1 month(s)
Omar: premium plan for 12 month(s)

Common mistakes with constructors

1. Adding a return type

void Lamp() { ... } is not a constructor. It's an ordinary method that happens to share the class name, so it never runs during new. Constructors have no return type at all.

2. Expecting the default constructor after writing your own

Once you write any constructor, new ClassName() only works if you also write a no-arg constructor yourself.

3. Putting code before this(...)

this(...) must be the first line of the constructor.

4. Misspelling the class name

A constructor named lamp() in class Lamp doesn't count; Java sees a method with a missing return type and reports an error.

5. Calling a constructor like a method

You can't write pizza.Pizza("large") to "reset" an object. Constructors run only through new (or this(...) inside another constructor).

Practice exercise

🏋️ Try it yourself

A shipping desk sends parcels. Write a Parcel class with fields destination, weightKg and speed. Give it a three-parameter constructor that sets all fields, and a one-parameter constructor (just the destination) that chains to it with a weight of 0.5 kg and the speed "standard". Create a letter to Madrid with the short constructor and a 4.5 kg express box to Sydney with the long one, then print both.

Show solution
public class ShippingDesk {
    public static void main(String[] args) {
        Parcel letter = new Parcel("Madrid");
        Parcel box = new Parcel("Sydney", 4.5, "express");

        letter.show();
        box.show();
    }
}

class Parcel {
    String destination;
    double weightKg;
    String speed;

    Parcel(String chosenDestination) {
        this(chosenDestination, 0.5, "standard");
    }

    Parcel(String chosenDestination, double chosenWeight, String chosenSpeed) {
        destination = chosenDestination;
        weightKg = chosenWeight;
        speed = chosenSpeed;
    }

    void show() {
        System.out.println(weightKg + " kg to " + destination + " (" + speed + ")");
    }
}
0.5 kg to Madrid (standard)
4.5 kg to Sydney (express)

The short constructor does no work of its own; it just fills in the defaults and passes everything to the main constructor.

What's next?

You may have noticed names like ownerName and chosenSize, used so the parameters don't clash with the field names. There's a cleaner way. Next, learn the Java this keyword, which lets parameters and fields share the same name.

Key takeaways

  • A constructor runs automatically during new and sets up the new object.
  • A constructor has the same name as the class and no return type, not even void.
  • If a class has no constructors, Java adds an empty default constructor; writing any constructor removes it.
  • Parameterized constructors let each object start with its own values.
  • Constructor overloading means several constructors with different parameter lists.
  • this(...) calls another constructor of the same class and must be the first statement.
  • Validate values in the constructor so every object starts out complete and valid.

Frequently asked questions

What is a constructor in Java?

A constructor is a special block with the same name as its class and no return type. It runs automatically when you create an object with new and gives the object its starting values.

What is the default constructor in Java?

It is the empty, no-argument constructor that Java adds automatically when a class declares no constructors at all. It leaves every field at its default value.

Can a constructor return a value?

No. A constructor has no return type. If you write void or another type in front of it, Java treats it as an ordinary method instead of a constructor.

What is constructor overloading?

Constructor overloading means giving a class more than one constructor, each with a different parameter list. Java chooses the one that matches the arguments passed to new.

What does this() do in a constructor?

this(...) calls another constructor of the same class. It lets short constructors pass default values to one main constructor, and it must be the first statement in the constructor.

Why do I get "constructor cannot be applied to given types"?

You called a constructor with arguments that do not match any constructor in the class. A common cause is calling new X() after writing only a constructor with parameters, which removes the default constructor.