Lesson 12 — Object Initialisation

Constructors

Constructors are special methods that initialise an object the moment it is created. They eliminate the tedious, error-prone process of setting every field manually after creation.

Why Constructors?

In Lesson 11 you created objects and then set each field individually — three or four separate lines per object. This is verbose, and worse, it allows objects to exist in an uninitialised state (some fields set, others not). A constructor solves both problems: you pass all required data at creation time, and the object is fully initialised in one atomic step.

Writing a Constructor

A constructor looks like a method but has no return type (not even void) and must have exactly the same name as the class. It runs automatically when new is called.

JAVA — Constructor
public class Learner {

    private String name;
    private int    age;
    private String course;
    private double mark;

    // Constructor — same name as class, no return type
    public Learner(String name, int age, String course, double mark) {
        this.name   = name;   // this.name = field, name = parameter
        this.age    = age;
        this.course = course;
        this.mark   = mark;
    }

    public void introduce() {
        System.out.printf("I am %s (%d), studying %s. Current mark: %.1f%%.
",
            name, age, course, mark);
    }

}

// Usage — object fully initialised in one line:
Learner l1 = new Learner("Thandi", 21, "Java", 74.5);
Learner l2 = new Learner("Sipho",  24, "Python", 81.0);
l1.introduce();
l2.introduce();

The this Keyword

this refers to the current object — the specific instance the code is running on. Inside a constructor (or instance method), when the parameter name is the same as the field name, this.name refers to the field and name refers to the parameter. Without this., the parameter shadows the field and the field is never assigned — a subtle, silent bug.

JAVA — The this keyword
public class Point {
    double x, y;

    // With this — correct:
    public Point(double x, double y) {
        this.x = x;  // field x gets the parameter value
        this.y = y;
    }

    // Without this — bug:
    // public Point(double x, double y) {
    //     x = x; // assigns parameter to itself — field stays 0
    //     y = y; // same bug
    // }

    // Using this to call another constructor:
    public Point() {
        this(0.0, 0.0); // delegates to the two-param constructor
    }
}

Constructor Overloading

Like methods, constructors can be overloaded — multiple constructors with different parameter lists give callers flexibility in how they create objects.

JAVA — Constructor overloading
public class Learner {
    private String name;
    private int    age;
    private String course;
    private double mark;

    // Full constructor
    public Learner(String name, int age, String course, double mark) {
        this.name   = name;
        this.age    = age;
        this.course = course;
        this.mark   = mark;
    }

    // Constructor without mark (defaults to 0.0)
    public Learner(String name, int age, String course) {
        this(name, age, course, 0.0); // calls the full constructor
    }

    // Minimal constructor
    public Learner(String name) {
        this(name, 0, "Undecided", 0.0);
    }

    public void printSummary() {
        System.out.printf("%-15s | %-10s | %.1f%%%n", name, course, mark);
    }
}

// Multiple ways to create a Learner:
Learner a = new Learner("Thandi", 21, "Java", 74.5);
Learner b = new Learner("Sipho",  24, "Python");     // no mark yet
Learner c = new Learner("Lerato");                    // minimal info
a.printSummary();
b.printSummary();
c.printSummary();

The Default Constructor

If you write no constructors at all, Java provides a free default constructor with no parameters that initialises all fields to their default values (0, false, null). The moment you write any constructor yourself, this free default disappears. If you still want a no-argument constructor, you must write it explicitly.

JAVA — Default constructor
public class Counter {
    int count; // auto-initialised to 0

    // No constructor written — Java provides Counter() for free
}

// This works:
Counter c = new Counter();
System.out.println(c.count); // 0

// But if you add this:
public Counter(int start) { this.count = start; }
// Then Counter() no longer works — you must add it back explicitly if needed:
public Counter() { this(0); }

Practice Task

Your Turn

Rewrite your BankAccount class from Lesson 11 to use constructors. Write: (1) a full constructor taking accountNumber, holderName, and initialBalance, (2) a constructor that takes only holderName and assigns a generated accountNumber (tip: use a static counter that increments). Make sure no field is left uninitialised. Create five accounts mixing both constructors and print their statements.

Common Mistakes

  • Adding a return type to a constructor — even void — turns it into an ordinary method that the JVM will never call as a constructor.
  • Forgetting this. when field and parameter share the same name — the field is never set.
  • Assuming the default no-arg constructor still exists after writing your own — it does not.
  • Using this(...) to call another constructor: this call must be the very first statement in the constructor body.
  • Performing complex logic in constructors — constructors should initialise fields and do little else. Heavy computation belongs in separate methods.

Professional Tip

A well-designed constructor makes it impossible to create an object in an invalid state. If certain fields are required, require them in the constructor — do not make them optional and rely on the caller to set them.

Mini Quiz

What is the return type of a constructor in Java?