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.
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.
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.
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.
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?