How does constructor overloading work, and how do you avoid writing two constructors that the compiler cannot tell apart?
Overloaded constructors are simply several constructors with different parameter lists on the same class. The compiler selects between them using the same rules it applies to overloaded methods, so the argument types and count have to be distinguishable at the call site. Two constructors may not have the same parameter types in the same order.
public class Main {
public static void main(String[] args) {
Money a = new Money(1050);
Money b = new Money(10, 50);
Money c = new Money("3.25");
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
class Money {
private final long minorUnits;
Money(long minorUnits) { this.minorUnits = minorUnits; }
Money(long whole, long cents) { this(whole * 100 + cents); }
Money(String text) { this(Long.parseLong(text.replace(".", ""))); }
public String toString() { return (minorUnits / 100) + "." + (minorUnits % 100); }
}The output shows the three shapes working. The single-argument constructor takes an amount already expressed in minor units, the two-argument version combines units and cents, and the string version parses a textual amount. All three funnel into the one constructor that actually assigns the field, so there is a single place where the invariant of the class is established.
Delegation with this is the technique worth highlighting. It keeps the constructors thin and avoids repeating validation or conversion logic in each overload. The rule to remember is that a this call must be the first statement in the constructor, and that a constructor can delegate to at most one other constructor, so a cycle of delegating constructors is a compile error.
The trap to mention is overloading on similar types. If you have one constructor taking an int and another taking a long, a call with an int literal picks the int version, which may not be what the caller assumed. When two overloads behave differently for similar arguments, a factory method with a descriptive name is often clearer than another constructor.