Hiprup

What is the difference between method overloading and method overriding?

Both method overloading and method overriding are forms of polymorphism, but they work at different times and places. Overloading means defining multiple methods with the same name but different parameter lists (number, type, or order of parameters) in the same class; the compiler picks the version to call, so it is compile-time (static) polymorphism. Overriding means a subclass supplies its own implementation of an inherited superclass method with the same signature; the JVM picks the version at runtime based on the actual object, so it is runtime (dynamic) polymorphism.

  • Overloading rules — parameter lists must differ; changing only the return type or access modifier does not overload and causes a compile error.

  • Overriding rules — same name and parameters, same or covariant return type; the subclass cannot reduce visibility or throw broader checked exceptions. Use @Override to catch signature mistakes.

  • What cannot be overriddenprivate, static, and final methods; a static method with the same signature is hidden, not overridden.

  • Binding — overloading is resolved at compile time from reference and argument types; overriding is resolved at runtime through dynamic method dispatch.

  • In automation frameworks — TestNG's Assert.assertEquals and the Selenium Actions class's sendKeys are heavily overloaded, while a ChromeTest overriding a base class's setUp() is everyday overriding in a framework.

Key terms: method overloading, method overriding, compile-time polymorphism, runtime polymorphism, dynamic method dispatch, covariant return type, @Override

class Browser {
    // Overloading: same method name, different parameter lists (same class)
    void open(String url) {
        System.out.println("Opening " + url + " with default timeout");
    }

    void open(String url, int timeoutSec) {
        System.out.println("Opening " + url + " with timeout " + timeoutSec + "s");
    }

    void launch() {
        System.out.println("Launching generic browser");
    }
}

class ChromeBrowser extends Browser {
    // Overriding: same signature as the superclass method, new behavior
    @Override
    void launch() {
        System.out.println("Launching Chrome with ChromeDriver");
    }
}

public class OverloadVsOverride {
    public static void main(String[] args) {
        Browser b = new Browser();
        b.open("https://example.com");       // Output: Opening https://example.com with default timeout
        b.open("https://example.com", 30);   // Output: Opening https://example.com with timeout 30s

        Browser ref = new ChromeBrowser();   // superclass reference, subclass object
        ref.launch();                        // Output: Launching Chrome with ChromeDriver
    }
}

The two open() methods demonstrate overloading: the compiler chooses between them at compile time purely from the argument list, which is why open("...") and open("...", 30) print different messages. launch() demonstrates overriding: even though the reference type is Browser, the JVM dispatches to ChromeBrowser's version at runtime because the actual object is a ChromeBrowser — this is dynamic method dispatch. The pattern mirrors real automation frameworks, where a base class defines generic driver setup and browser-specific subclasses override it.

Lead with the crisp contrast — same class plus different parameters versus subclass plus same signature — then immediately name the binding difference (compile time vs runtime), because that phrase is what interviewers listen for. Expect follow-ups: can you overload by return type alone (no), can static, private, or final methods be overridden (no; static is hidden), and can constructors be overloaded or overridden (overloaded yes, overridden no).

The classic mistake is calling overriding "overloading across classes" or forgetting that overriding cannot reduce visibility or widen checked exceptions.