How does constructor overloading work in Java, and how do you avoid duplicating initialisation logic across the overloads?
Constructors are overloaded exactly like methods: several constructors in one class with different parameter lists, and the compiler picks one based on the arguments at the call site. The parameter types are the whole signature — the number of arguments, their types and their order.
The problem that overloading creates is duplication. If four constructors each assign the same four fields, then changing how one field is initialised means editing four places, and forgetting one is a silent bug. The fix is constructor chaining: one constructor does the real work, and the others delegate to it with the this(...) call, filling in defaults for the arguments they do not take.
public class Main {
public static void main(String[] args) {
System.out.println(new Point(1, 2));
System.out.println(new Point(3, 4, 10));
System.out.println(new Point(5, 6, 10, false));
}
}
class Point {
private final int x;
private final int y;
private final int z;
private final boolean visible;
// The full constructor does the real work.
Point(int x, int y, int z, boolean visible) {
this.x = x;
this.y = y;
this.z = z;
this.visible = visible;
}
// The others delegate to it, supplying defaults.
Point(int x, int y) {
this(x, y, 0, true);
}
Point(int x, int y, int z) {
this(x, y, z, true);
}
@Override
public String toString() {
return "(" + x + ", " + y + ", " + z + ") visible=" + visible;
}
}The output shows all three overloads producing consistent objects, with the defaults coming from a single place. That is the real benefit of chaining: the defaults live in one constructor, so changing them is a one-line edit.
Two design points worth adding. Keeping the full constructor as the one that assigns the fields means the class has exactly one place where the object is built, which is easier to reason about. And if your class is immutable — final fields assigned in every constructor — chaining also removes the risk of forgetting to initialise one of them, because only one constructor assigns anything directly.