Skip to content

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

  1. Same method name
  2. Different parameter lists (number, type, or order of parameters)
  3. Return type alone is not sufficient for overloading
  4. 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

  1. Keep overloaded methods semantically similar: They should perform similar operations
  2. Avoid confusing overloads: Don't overload methods that do completely different things
  3. Use descriptive parameter names: Helps distinguish between overloads
  4. Consider using static factory methods: Alternative to constructor overloading
  5. 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;
    }
}