What is method overloading in Java, and what rules does the compiler use to choose between the overloads?
Overloading means giving a class several methods with the same name but different parameter lists. The compiler picks the overload at compile time, using the static types of the arguments and a three-step resolution process.
Step one considers only methods that are applicable without any boxing or unboxing. If exactly one of those applies, it wins. Step two repeats the search allowing boxing and unboxing. Step three allows widening primitive conversions. If two candidates are equally good at any stage, the call is ambiguous and fails to compile.
What makes two methods different overloads is their parameter list — the types and the number of the parameters. Parameter names do not matter, and neither does the return type. The order of the parameter types matters, so log(String, int) and log(int, String) are two distinct overloads.
public class Main {
public static void main(String[] args) {
System.out.println(describe(42)); // int
System.out.println(describe(42L)); // long
System.out.println(describe("forty two")); // String
System.out.println(describe(42, 2)); // the two-argument version
System.out.println(describe(4.2)); // double
}
static String describe(int value) {
return "int " + value;
}
static String describe(long value) {
return "long " + value;
}
static String describe(double value) {
return "double " + value;
}
static String describe(String value) {
return "String " + value;
}
static String describe(int value, int times) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < times; i++) {
sb.append(value).append(' ');
}
return sb.toString().trim();
}
}The commonest overloading trap is a null literal. Given overloads for String and StringBuilder, the call describe(null) is ambiguous because null matches both and neither is more specific, so it will not compile. The fixes are an explicit cast, or removing one of the overloads. A second trap is overloads that differ only by boxing: with both an int and an Integer overload, an int argument prefers the primitive one and an Integer argument prefers the wrapper one, so changing how the caller boxes the value silently changes which method runs.