5.3. Method Overloading
Method overloading allows a class to have multiple methods with the same name but different parameters. It provides polymorphism at compile-time and makes APIs more intuitive to use.
Overloading Rules
- Same method name
- Different parameter lists (number, type, or order of parameters)
- Return type alone is not sufficient for overloading
- Access modifiers can be different
Basic Method Overloading Examples
Overloading by Parameter Number
java
public class Calculator {
// Add two integers
public int add(int a, int b) {
System.out.println("Adding two integers: " + a + " + " + b);
return a + b;
}
// Add three integers
public int add(int a, int b, int c) {
System.out.println("Adding three integers: " + a + " + " + b + " + " + c);
return a + b + c;
}
// Add variable number of integers
public int add(int... numbers) {
System.out.println("Adding " + numbers.length + " integers");
int sum = 0;
for (int num : numbers) {
sum += num;
}
return sum;
}
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println("Result: " + calc.add(5, 3)); // Two parameters
System.out.println("Result: " + calc.add(1, 2, 3)); // Three parameters
System.out.println("Result: " + calc.add(1, 2, 3, 4, 5)); // Varargs
}
}
Overloading by Parameter Type
java
public class MathOperations {
// Integer addition
public int add(int a, int b) {
System.out.println("Integer addition");
return a + b;
}
// Double addition
public double add(double a, double b) {
System.out.println("Double addition");
return a + b;
}
// String concatenation
public String add(String a, String b) {
System.out.println("String concatenation");
return a + b;
}
// Mixed types
public String add(String a, int b) {
System.out.println("String and integer concatenation");
return a + b;
}
public String add(int a, String b) {
System.out.println("Integer and string concatenation");
return a + b;
}
public static void main(String[] args) {
MathOperations ops = new MathOperations();
System.out.println("Result: " + ops.add(5, 3)); // Integer
System.out.println("Result: " + ops.add(5.5, 3.2)); // Double
System.out.println("Result: " + ops.add("Hello", "World")); // String
System.out.println("Result: " + ops.add("Number: ", 42)); // Mixed
System.out.println("Result: " + ops.add(100, " points")); // Mixed
}
}
Constructor Overloading
java
public class Person {
private String name;
private int age;
private String email;
private String phone;
// Default constructor
public Person() {
this.name = "Unknown";
this.age = 0;
this.email = "Not provided";
this.phone = "Not provided";
}
// Constructor with name only
public Person(String name) {
this.name = name;
this.age = 0;
this.email = "Not provided";
this.phone = "Not provided";
}
// Constructor with name and age
public Person(String name, int age) {
this.name = name;
this.age = age;
this.email = "Not provided";
this.phone = "Not provided";
}
// Full constructor
public Person(String name, int age, String email, String phone) {
this.name = name;
this.age = age;
this.email = email;
this.phone = phone;
}
// Copy constructor
public Person(Person other) {
this.name = other.name;
this.age = other.age;
this.email = other.email;
this.phone = other.phone;
}
@Override
public String toString() {
return String.format("Person{name='%s', age=%d, email='%s', phone='%s'}",
name, age, email, phone);
}
public static void main(String[] args) {
Person person1 = new Person(); // Default
Person person2 = new Person("Alice"); // Name only
Person person3 = new Person("Bob", 25); // Name and age
Person person4 = new Person("Charlie", 30,
"charlie@email.com",
"123-456-7890"); // Full
Person person5 = new Person(person4); // Copy
System.out.println(person1);
System.out.println(person2);
System.out.println(person3);
System.out.println(person4);
System.out.println(person5);
}
}
Advanced Overloading Examples
Geometric Shapes Calculator
java
public class GeometryCalculator {
// Circle area
public double calculateArea(double radius) {
System.out.println("Calculating circle area with radius: " + radius);
return Math.PI * radius * radius;
}
// Rectangle area
public double calculateArea(double length, double width) {
System.out.println("Calculating rectangle area: " + length + " x " + width);
return length * width;
}
// Triangle area
public double calculateArea(double base, double height, String shape) {
if ("triangle".equalsIgnoreCase(shape)) {
System.out.println("Calculating triangle area: base=" + base + ", height=" + height);
return 0.5 * base * height;
}
throw new IllegalArgumentException("Unknown shape: " + shape);
}
// Cube volume
public double calculateVolume(double side) {
System.out.println("Calculating cube volume with side: " + side);
return side * side * side;
}
// Cylinder volume
public double calculateVolume(double radius, double height) {
System.out.println("Calculating cylinder volume: radius=" + radius + ", height=" + height);
return Math.PI * radius * radius * height;
}
// Rectangular prism volume
public double calculateVolume(double length, double width, double height) {
System.out.println("Calculating rectangular prism volume: " +
length + " x " + width + " x " + height);
return length * width * height;
}
}
Database Connection Example
java
public class DatabaseConnection {
private String url;
private String username;
private String password;
private int timeout;
private boolean useSSL;
// Minimal constructor
public DatabaseConnection(String url) {
this(url, null, null);
}
// Constructor with authentication
public DatabaseConnection(String url, String username, String password) {
this(url, username, password, 30, false);
}
// Full constructor
public DatabaseConnection(String url, String username, String password,
int timeout, boolean useSSL) {
this.url = url;
this.username = username;
this.password = password;
this.timeout = timeout;
this.useSSL = useSSL;
}
// Static factory methods (alternative to constructors)
public static DatabaseConnection createLocalConnection() {
return new DatabaseConnection("jdbc:mysql://localhost:3306/mydb");
}
public static DatabaseConnection createRemoteConnection(String host) {
return new DatabaseConnection("jdbc:mysql://" + host + ":3306/mydb",
"remote_user", "remote_pass", 60, true);
}
public static DatabaseConnection createSecureConnection(String url) {
return new DatabaseConnection(url, null, null, 45, true);
}
}
Method Resolution in Overloading
java
public class OverloadingResolution {
public void process(int number) {
System.out.println("Processing integer: " + number);
}
public void process(double number) {
System.out.println("Processing double: " + number);
}
public void process(String text) {
System.out.println("Processing string: " + text);
}
public void process(Object obj) {
System.out.println("Processing object: " + obj);
}
public void process(int... numbers) {
System.out.println("Processing varargs: " + Arrays.toString(numbers));
}
public static void main(String[] args) {
OverloadingResolution resolver = new OverloadingResolution();
resolver.process(10); // Exact match: int
resolver.process(10.5); // Exact match: double
resolver.process("Hello"); // Exact match: String
resolver.process(10L); // Widening: long -> double
resolver.process(10.0f); // Widening: float -> double
resolver.process(null); // Most specific: String (if String is most specific)
// The compiler chooses the most specific method
byte b = 5;
resolver.process(b); // Widening: byte -> int
Integer integer = 10;
resolver.process(integer); // Auto-unboxing: Integer -> int
}
}
Best Practices for Method Overloading
- Keep overloaded methods semantically similar: They should perform similar operations
- Avoid confusing overloads: Don't overload methods that do completely different things
- Use descriptive parameter names: Helps distinguish between overloads
- Consider using static factory methods: Alternative to constructor overloading
- Document each overload: Explain when to use which version
java
/**
* Utility class for string operations with method overloading
*/
public class StringUtils {
/**
* Checks if a string contains the given substring
* @param text the text to search in
* @param substring the substring to find
* @return true if the substring is found
*/
public static boolean contains(String text, String substring) {
return text != null && substring != null && text.contains(substring);
}
/**
* Checks if a string contains any of the given substrings
* @param text the text to search in
* @param substrings the substrings to find
* @return true if any substring is found
*/
public static boolean contains(String text, String... substrings) {
if (text == null || substrings == null) return false;
for (String substring : substrings) {
if (substring != null && text.contains(substring)) {
return true;
}
}
return false;
}
/**
* Checks if a string contains the given character
* @param text the text to search in
* @param ch the character to find
* @return true if the character is found
*/
public static boolean contains(String text, char ch) {
return text != null && text.indexOf(ch) >= 0;
}
}