1. Method overloading
Method overloading is the ability to declare multiple methods with the same name but different parameter lists (types, counts, or order of arguments) within a single class. When you call such a method, the compiler decides which version to use based on the arguments you pass.
A real-world analogy
Imagine calling a bank’s support service. You can dial different numbers — for individuals, for businesses, for VIP clients. The numbers differ, but the goal is the same — to get help. In programming, method overloading is like a single support number that automatically routes you to the right operator depending on your question (or which parameters you passed).
Overloading syntax in Java
In Java, method overloading is straightforward: you declare several methods with the same name but different parameters.
Important rule:
Overloads differ only by parameter list (type, count, order).
Overloading by return type only is not allowed!
The compiler cannot distinguish methods if they have the same name and the same parameters, even if the return type differs.
Simple example
public class Printer {
// Print an int
void print(int x) {
System.out.println("int: " + x);
}
// Print a string
void print(String s) {
System.out.println("String: " + s);
}
// Print two numbers
void print(int x, int y) {
System.out.println("int, int: " + x + ", " + y);
}
}
Usage:
Printer printer = new Printer();
printer.print(42); // calls print(int x)
printer.print("Hello!"); // calls print(String s)
printer.print(5, 10); // calls print(int x, int y)
The compiler determines which method to call based on the provided arguments.
2. How the compiler selects the right method
When you call an overloaded method, the compiler analyses the argument list and looks for the best-matching version.
Selection criteria:
- Matching the number of arguments.
- Matching the type of each argument (or the ability to convert the type, for example, int → double).
- If several methods match, the most specific one is chosen.
Example:
public class OverloadDemo {
void show(int x) {
System.out.println("show(int): " + x);
}
void show(double x) {
System.out.println("show(double): " + x);
}
public static void main(String[] args) {
OverloadDemo demo = new OverloadDemo();
demo.show(5); // show(int): 5
demo.show(5.5); // show(double): 5.5
}
}
If you call demo.show(5), the compiler will choose show(int). If you call it with 5.5 — it will choose show(double).
Type conversions
If there’s no suitable method, the compiler will try to convert argument types (for example, int → double), but only if this is possible and unambiguous.
void print(double x) { /* ... */ }
print(5); // int 5 is converted to double 5.0
Overloading by return type only — does not work!
Many beginners try this:
// Error! This kind of overloading is not allowed
int sum(int x, int y) { return x + y; }
double sum(int x, int y) { return (double) (x + y); }
The compiler won’t know which method you want to call if you just write sum(2, 3).
Remember: method overloading is only possible by parameters, not by return type!
3. Constructor overloading
You can overload not only regular methods but also constructors!
public class Person {
String name;
int age;
// Constructor with name only
public Person(String name) {
this.name = name;
this.age = 0; // default
}
// Constructor with name and age
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Usage:
Person p1 = new Person("Anna");
Person p2 = new Person("Boris", 25);
4. Practical examples
Calculator with overloading
Let’s write a Calculator class that can add numbers of different types and counts.
public class Calculator {
// Add two ints
int add(int a, int b) {
return a + b;
}
// Add three ints
int add(int a, int b, int c) {
return a + b + c;
}
// Add two doubles
double add(double a, double b) {
return a + b;
}
}
Usage:
Calculator calc = new Calculator();
System.out.println(calc.add(2, 3)); // 5
System.out.println(calc.add(1, 2, 3)); // 6
System.out.println(calc.add(2.5, 3.1)); // 5.6
Overloading in the standard library
You’ve already encountered overloading, even if you didn’t notice it. For example, the println method in System.out is overloaded for different types:
System.out.println("Hello"); // println(String)
System.out.println(123); // println(int)
System.out.println(3.14); // println(double)
System.out.println(true); // println(boolean)
Open the sources of the PrintStream class — you’ll see dozens of overloaded versions of println.
5. When to use overloading
Method overloading is a powerful tool, but use it wisely. It’s handy when:
- The method’s logic is the same, but the parameters can differ.
- You want to make a class API more friendly and flexible.
- You need to support both old and new ways of calling a method.
Real-world example:
In our training app (for example, a task manager), you can implement a method for adding a task with different parameters:
public class TaskManager {
void addTask(String description) { ... }
void addTask(String description, int priority) { ... }
void addTask(String description, int priority, String deadline) { ... }
}
This approach is not only convenient for the code’s user but also makes your class flexible for future changes.
6. Overloading and varargs (variable number of arguments)
In Java, you can declare a method with a variable number of parameters using ... (varargs):
void printAll(String... messages) {
for (String msg : messages) {
System.out.println(msg);
}
}
Now you can call:
printAll("Hello");
printAll("One", "Two", "Three");
You can overload with varargs too, but be careful: if you have two methods and one of them uses varargs while the other has a fixed number of parameters, the compiler will first try to find an exact match.
7. Common mistakes with method overloading
Error #1: Confusion with argument types.
If you have methods void process(int x) and void process(double x), the call process(5) will invoke the first version, and process(5.0) — the second. But if you call process(5L), the compiler will search for the best match and may pick a non-obvious overload (or even report ambiguity).
Error #2: Overloading with autoboxing/automatic conversions.
If you have void foo(Integer x) and void foo(Long x), the call foo(5) will lead to a compilation error — the compiler doesn’t know which method to choose, because 5 can be converted to both Integer and Long.
Error #3: Overloading by return type only.
As mentioned above, methods that differ only by return type cannot be overloaded.
Error #4: Overloading and inheritance.
If a method is declared in a base class, and in a subclass you declare a method with the same name but a different signature, that will be overloading, not overriding. This is often confused! More on this in the next lecture.
GO TO FULL VERSION