Project Based Learning in Java

Method Overloading and Overriding

Compile-time overloading, runtime overriding, type promotion, and super.

Lecture 1.2.3 CO2 aligned Unit 1

Learning outcome: Distinguish method overloading from method overriding and apply the rules of each correctly.

Overloading gives several methods the same name with different parameter lists. Overriding lets a child class replace an inherited instance-method implementation.

Method Overloading

Methods are overloaded when they have the same name but different parameter lists in the same class or inheritance hierarchy.

In simple terms: Overloading is one word carrying several meanings, chosen by context — “book a table” and “read a book”. The compiler picks from the arguments supplied, before the program ever runs.

class Calculator {
    static int add(int a, int b) {
        return a + b;
    }

    static int add(int a, int b, int c) {
        return a + b + c;
    }

    static double add(double a, double b) {
        return a + b;
    }
}

The compiler selects a method using the number, types, and order of arguments.

Valid Ways to Overload

Change Valid overload? Example
Number of parameters Yes show(int) and show(int, int)
Parameter types Yes show(int) and show(String)
Parameter order Yes, if the sequence of types differs show(int, String) and show(String, int)
Return type only No int show() and double show() conflict
Parameter names only No Names are not part of a method signature

Return type alone cannot resolve a call because a caller may ignore the returned value.

Type Promotion in Overloading

If no exact overload exists, Java may widen a compatible primitive argument.

In simple terms: With no exact match, Java widens rather than narrows: an int will happily be treated as a long, but never silently squeezed into a byte.

class PromotionDemo {
    static void print(long value) {
        System.out.println("long: " + value);
    }

    public static void main(String[] args) {
        int number = 25;
        print(number);       // int widens to long
    }
}

Avoid overload sets that make calls ambiguous. Clear APIs are more important than having many similar overloads.

Method Overriding

A child class overrides an inherited instance method by declaring a compatible method with the same signature.

In simple terms: Overriding is a child giving its own answer to a question the parent already answered. Which answer is used is decided while the program runs, from the actual object.

class Notification {
    void send() {
        System.out.println("Generic notification");
    }
}

class EmailNotification extends Notification {
    @Override
    void send() {
        System.out.println("Email sent");
    }
}

Use @Override. It asks the compiler to confirm that a valid inherited method is being overridden.

Overriding Rules

Rule Meaning
Same method name and parameter list The child method must match the inherited signature.
Compatible return type It must be the same type, or a more specific reference type where covariance is allowed.
Access cannot be more restrictive A public parent method cannot become protected or private.
Checked exceptions cannot be new or broader The child may declare fewer checked exceptions or compatible subtypes, but not an unrelated or broader checked type; unchecked exceptions are not restricted by this rule.
final methods cannot be overridden final fixes the inherited implementation.
Private methods are not overridden They are not inherited as accessible methods.
Constructors are not overridden Constructors belong to the class that declares them.

Calling the Parent Implementation

Use super.methodName() when the child wants to extend, rather than completely replace, parent behaviour.

In simple terms: super.method() is adding to what the parent already does rather than replacing it — the parent’s work happens, then the child’s extra step.

class Report {
    void print() {
        System.out.println("Report header");
    }
}

class SalesReport extends Report {
    @Override
    void print() {
        super.print();
        System.out.println("Sales data");
    }
}

Static Methods and main

Static methods are associated with a class and are hidden, not overridden. Selection uses the reference type rather than the runtime object.

In simple terms: Static methods are hidden, not overridden. The reference type decides which one runs, so the polymorphism you would expect simply does not apply.

The main method can be overloaded, but on the JDK 17 course baseline the Java launcher starts the standard entry-point signature:

public static void main(String[] args)

The equivalent varargs spelling public static void main(String... args) is also valid because String... compiles as String[]. Other main overloads run only when called explicitly.

Overloading vs Overriding

Feature Overloading Overriding
Purpose Multiple ways to call related behaviour Specialised child behaviour
Parameters Must differ Must match
Inheritance required No Yes
Binding Compile time Runtime for instance methods
Return type May differ when parameters differ Same or covariant
Static methods Can be overloaded Hidden, not overridden

Common Mistakes

Mistake Correction
Changing only the return type Change the parameter list instead.
Misspelling an overriding method Add @Override so the compiler detects it.
Reducing visibility in a child method Keep the same or broader access.
Expecting a static method to behave polymorphically Static methods are hidden, not overridden; use instance methods for runtime dispatch.

Practice

  1. Overload area() for a square, rectangle, and circle.
  2. Create an Employee parent whose calculatePay() is overridden by two child classes.
  3. Predict which overload runs when an int is passed to methods accepting long and double.
  4. Explain why int convert(String) and double convert(String) cannot coexist.

Quick Check

1. Can two overloads differ only by return type?

No. Their parameter lists must differ.

2. Why should @Override be used?

It lets the compiler verify that the method correctly overrides an inherited method.

3. Are static methods overridden?

No. Static methods can be overloaded or hidden, but runtime overriding applies to instance methods.

Summary

Overloading is compile-time selection among methods with different parameter lists. Overriding supplies specialised child behaviour and enables runtime polymorphism. Correct signatures, access levels, return types, and exception rules keep both mechanisms predictable.