Object-Oriented Programming Basics

Constructors & the this Keyword

15 min Lesson 3 of 14

Constructors & the this Keyword

In the previous lesson you gave a class fields and methods that describe state and behaviour. But how does an object come to life with meaningful data in the first place? That is the job of a constructor. And once you are inside a constructor, how do you refer to the object being built? That is the job of the this keyword.

What is a Constructor?

A constructor is a special method that Java calls automatically when you write new ClassName(...). It looks like a method but has no return type (not even void) and its name must match the class exactly, including capitalisation.

Key idea: A constructor does not create the object — the JVM allocates memory first. The constructor's job is to initialise the fields of the freshly allocated object before anyone else can use it.

The Default Constructor

If you write no constructor at all, Java silently generates a default (no-argument) constructor for you. It initialises every field to its zero value: 0 for numbers, false for booleans, and null for object references.

public class BankAccount { String owner; double balance; // No constructor written — Java supplies: // public BankAccount() { } } // Usage BankAccount acct = new BankAccount(); System.out.println(acct.owner); // null System.out.println(acct.balance); // 0.0

This is fine for a quick prototype, but most real classes need their fields set to meaningful values right at creation time.

The default constructor disappears once you write any constructor yourself. If you add a parameterised constructor and still want a no-argument constructor, you must write both explicitly.

Parameterised Constructors

A parameterised constructor accepts arguments so callers can supply the initial state:

public class BankAccount { String owner; double balance; // Parameterised constructor public BankAccount(String owner, double balance) { this.owner = owner; this.balance = balance; } } // Usage BankAccount acct = new BankAccount("Alice", 1000.00); System.out.println(acct.owner); // Alice System.out.println(acct.balance); // 1000.0

Now every BankAccount is guaranteed to start with a named owner and an explicit balance. The compiler will refuse to let you call new BankAccount() without arguments, which prevents accidentally creating accounts with null owners.

The this Keyword — Disambiguation

In the example above, the constructor parameter is named owner and so is the field. Inside the constructor, the local parameter shadows the field. Writing plain owner = owner would assign the parameter to itself — a no-op. this solves this cleanly:

  • this.owner — refers to the field on the current object.
  • owner (no prefix) — refers to the local parameter.
public BankAccount(String owner, double balance) { this.owner = owner; // field = parameter this.balance = balance; // field = parameter }

this is simply a reference to the object currently being constructed (or on which a method is being called). It is available in any non-static method or constructor.

Naming tip: Using the same name for parameters and fields (disambiguated with this) is the most common Java convention. It makes the intent crystal-clear: "assign the parameter to the same-named field."

Constructor Overloading

Java allows multiple constructors as long as their parameter lists differ (different count or types). This is called constructor overloading:

public class BankAccount { String owner; double balance; // Constructor 1 — owner and initial balance public BankAccount(String owner, double balance) { this.owner = owner; this.balance = balance; } // Constructor 2 — owner only, balance defaults to 0 public BankAccount(String owner) { this.owner = owner; this.balance = 0.0; } } BankAccount savings = new BankAccount("Bob", 500.00); BankAccount checking = new BankAccount("Bob"); // balance = 0.0

Constructor Chaining with this()

Duplicating initialisation logic across constructors is fragile — if the logic changes, you must update every copy. Constructor chaining solves this: one constructor calls another in the same class using this(...).

public class BankAccount { String owner; double balance; String currency; // The "canonical" constructor — all fields set here public BankAccount(String owner, double balance, String currency) { this.owner = owner; this.balance = balance; this.currency = currency; } // Convenience: default currency to "USD" public BankAccount(String owner, double balance) { this(owner, balance, "USD"); // calls the three-arg constructor } // Convenience: zero balance and USD public BankAccount(String owner) { this(owner, 0.0); // calls the two-arg constructor, which calls three-arg } }
Rule: A this(...) call must be the very first statement inside the constructor. You cannot do any other work before delegating. This guarantees the object is fully initialised before any additional logic runs.

The pattern — one fully-specified constructor doing all the work, shorter constructors delegating to it — keeps your initialisation logic in one place and is easy to maintain.

Summary

  • A constructor initialises a new object. It has no return type and matches the class name.
  • The default constructor is free when you write none; it vanishes once you write your own.
  • Parameterised constructors enforce that required data is supplied at creation.
  • this.field distinguishes a field from a same-named parameter inside a constructor or method.
  • this(...) chains one constructor to another in the same class and must be the first statement.