CodeToConcept
About

java

java Tutorials

Introduction
Java Variables
Java Data Types
Java Type Casting
Java Operators
Java Input/Output
Java Class & Object
java Method
Java Constructor
Java this keyword
Java super keyword
Java Method Overloading and Overriding
Java Interface
Java Abstract Class
Java Memory Management
Design Patterns
JDBC (Database Connectivity)
Java IDEs

java Tutorials

Introduction
Java Variables
Java Data Types
Java Type Casting
Java Operators
Java Input/Output
Java Class & Object
java Method
Java Constructor
Java this keyword
Java super keyword
Java Method Overloading and Overriding
Java Interface
Java Abstract Class
Java Memory Management
Design Patterns
JDBC (Database Connectivity)
Java IDEs

Sample Question

Think it through, then check the tutorial.

CodeToConcept

Quickly learn through simple, structured, and practical coding tutorials. Build your confidence from step zero to real-world experience.

© 2026 CodeToConcept. All rights reserved.

Quick Links

AboutTutorials

Tutorials

JavaHTMLCSS

Support

Privacy PolicyTerms of ServiceContact
GitHubTwitterYouTube

Java Method Overloading and Method Overriding

Method Overloading and Method Overriding are important concepts in Java and are closely related to polymorphism.

Both allow a method to have different behaviors based on the context. There are two different ways to achieve this:

  • Method Overloading → Same method name, different parameters.
  • Method Overriding → Child class provides a different implementation of a method inherited from the parent class.

Method Overloading in Java

What is Method Overloading?

Method overloading occurs when a class has multiple methods with the same name but different parameter lists.

The methods parameters can differ in terms of:

  • Number of parameters
  • Type of parameters
  • Order of parameters

We will see all 3 different ways in the examples below.

Example-1:

Different Number of Parameters

class ScoreTotal {
 
    int addTwoNumber(int a, int b) { //here we have two parameters
        return a + b;
    }
 
    int addThreeNumber(int a, int b, int c) { //here we have three parameters
        return a + b + c;
    }
}
addTwoNumber(int, int)
addThreeNumber(int, int, int)

Therefore, these methods are overloaded.

So here, the method addTwoNumber is overloaded with different number of parameters.

Example-2

Different Types of Parameters:

class ScoreTotal {
 
    int addTwoNumber(int a, int b) {//here we have two parameters of type int 
        return a + b;
    }
 
    double addTwoNumber(double a, double b) {//here we have two parameters of type double 
        return a + b;
    }
}

So here, the method name is the same, but the parameter types are different.

addTwoNumber(int, int)
addTwoNumber(double, double)

Here, the method addTwoNumber is overloaded with different parameter types.

Example-3:

Different Order of Parameters:

class ScoreTotal {
 
    int addTwoNumber(int a, double b) {//here we have two parameters, first of type int and second of type double
        return (int) (a + b);
    }
 
    int addTwoNumber(double a, int b) {//here we have two parameters, first of type double and second of type int
        return (int) (a + b);
    }
}

So here, the method name is the same, but the order of parameter types is different.

addTwoNumber(int, double)
addTwoNumber(double, int)

Here, the method addTwoNumber is overloaded with different order of parameter types.

Why Do We Need Method Overloading?

Suppose we want to add two or three numbers.

Without overloading, we use a different name for each method:

int addTwoNumber(int a, int b) {
    return a + b;
}
 
int addThreeNumber(int a, int b, int c) {
    return a + b + c;
}

We need to remember both method names. Also, it makes the code less readable and harder to maintain and make it more complex for developers to use correctly.

With overloading, we can use the same name, add, for both methods:

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

We call the methods like this:

public class HelloWorld {
    public static void main(String[] args) {
        ScoreTotal scores = new ScoreTotal();
        System.out.println(scores.add(8, 17));     // Output: 25
        System.out.println(scores.add(8, 17, 25)); // Output: 50
    }
}

Java chooses the method based on the number of arguments. We only need to remember one name: add.

Simple Example of Method Overloading

In this example, all three methods are named add. They accept different numbers or types of parameters.

class ScoreTotal {
    int add(int a, int b) {
        return a + b;
    }
 
    int add(int a, int b, int c) {
        return a + b + c;
    }
 
    double add(double a, double b) {
        return a + b;
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        ScoreTotal scores = new ScoreTotal();
 
        System.out.println(scores.add(8, 17));
        System.out.println(scores.add(8, 17, 25));
        System.out.println(scores.add(6.5, 9.5));
    }
}

Output

25
50
16.0

Java chooses the method based on the arguments:

  • add(8, 17) calls the method with two int parameters.
  • add(8, 17, 25) calls the method with three int parameters.
  • add(6.5, 9.5) calls the method with two double parameters.

The method name stays the same, but the parameter lists are different. This is method overloading.

How Does Method Overloading Work?

When we call an overloaded method, Java looks at the method name and the arguments we provide. The compiler checks the method name, the number of arguments, and their types. It then chooses the applicable overload. This choice happens at compile time hence it is known as compile-time polymorphism.

Example 1:

Different Numbers of Arguments

class ScoreTotal {
    int add(int a, int b) {
        return a + b;
    }
 
    int add(int a, int b, int c) {
        return a + b + c;
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        ScoreTotal scores = new ScoreTotal();
        System.out.println(scores.add(8, 17));
        System.out.println(scores.add(8, 17, 25));
    }
}

Output:

25
50

The first call has two int arguments, so Java selects add(int, int). The second has three int arguments, so Java selects add(int, int, int).

Example 2: Different Argument Types

class LessonLookup {
    void find(int lessonId) {
        System.out.println("Lesson ID: " + lessonId);
    }
 
    void find(String title) {
        System.out.println("Lesson title: " + title);
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        LessonLookup lessons = new LessonLookup();
        lessons.find(42);
        lessons.find("Java methods");
    }
}

Output:

Lesson ID: 42
Lesson title: Java methods

The number 42 has type int, so the first call selects find(int). The text has type String, so the second call selects find(String).

Example 3: Different Order of Argument Types

class LessonLabel {
    void show(int lessonId, String title) {
        System.out.println(lessonId + ": " + title);
    }
 
    void show(String title, int lessonId) {
        System.out.println(title + " (#" + lessonId + ")");
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        LessonLabel label = new LessonLabel();
        label.show(42, "Java methods");
        label.show("Java methods", 42);
    }
}

Output:

42: Java methods
Java methods (#42)

The first call selects show(int, String). The second selects show(String, int). The order matters because the sequence of parameter types is different.

Remember: Overloaded methods must share the same name. Methods named addTwoNumber and addThreeNumber are separate methods, not overloads of each other. Changing only the return type does not create an overload.

Type Promotion in Method Overloading

When we call an overloaded method, Java first looks for an exact match for the argument types. If it cannot find one, it tries to promote the arguments to compatible types.

For example, when there is a method having a long parameter, When we call it with an int argument, during compile time Java can convert an int to long when calling a method. You do not need to write a cast. So here the int variable minutes is automatically promoted to long when calling the show(long) method. This is an example of type promotion in method overloading.

Rules for Type Promotion in Method Overloading:

  1. Java first looks for an exact match for the argument types.
  2. If no exact match is found, Java tries to promote the arguments to compatible types.
  3. Widening conversions are preferred over narrowing conversions.
  4. Among multiple possible promotions, Java selects the most specific method.

Example 1:

Widening an int to long

class ReadingTime {
    void show(long minutes) {
        System.out.println("Whole minutes: " + minutes);
    }
 
    void show(String description) {
        System.out.println("Reading plan: " + description);
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        ReadingTime time = new ReadingTime();
        int minutes = 18;
        time.show(minutes);
        time.show("One lesson each evening");
    }
}

Output:

Whole minutes: 18
Reading plan: One lesson each evening

There is no show(int) method. Java widens the int argument to long and selects show(long). It does not convert the number into a String to call the other overload.

Example 2:

Choosing Between long and double

class ReadingTime {
    void show(long minutes) {
        System.out.println("long overload: " + minutes);
    }
 
    void show(double minutes) {
        System.out.println("double overload: " + minutes);
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        ReadingTime time = new ReadingTime();
        time.show(18);
        time.show(18.5);
    }
}

Output:

long overload: 18
double overload: 18.5

The int value 18 can widen to either long or double. Java selects show(long) because it is more specific here: long can widen to double, but double cannot widen to long. The value 18.5 is already a double, so it selects show(double).

If a show(int) overload were also available, the int argument would select that exact match in this example.

Reference Arguments: Object, String, Custom Classes, and null

The earlier examples use numeric type promotion. These examples use reference types. Java can pass a subtype reference to a parent-type parameter. The compiler chooses an overload using the argument's declared type, not the actual object stored in it.

null can be passed to any reference type, but not to a primitive type. If several overloads match, Java chooses the most specific one. Unrelated types can make the call ambiguous.

Run each example separately as HelloWorld.java.

Example 3: null, String, and Object

class LessonPrinter {
    void show(Object value) {
        System.out.println("Object overload");
    }
 
    void show(String value) {
        System.out.println("String overload");
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        LessonPrinter printer = new LessonPrinter();
        String title = "Java methods";
        Object savedTitle = title;
 
        printer.show(title);
        printer.show(savedTitle);
        printer.show(new Object());
        printer.show(null);
    }
}

Output:

String overload
Object overload
Object overload
String overload

A String argument selects show(String). An Object reference selects show(Object), even when it holds a String. Plain null matches both methods, but String is more specific than Object, so show(String) is selected.

Example 4: Passing a String to an Object Parameter

class LessonPrinter {
    void show(Object value) {
        System.out.println("Object overload: " + value);
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        LessonPrinter printer = new LessonPrinter();
        printer.show("Java methods");
    }
}

Output:

Object overload: Java methods

There is no show(String) method here. A String is also an Object, so Java can pass it to show(Object). The String object itself does not change.

Example 5: null and a Custom Class

class Lesson {
}
 
class LessonPrinter {
    void show(Object value) {
        System.out.println("Object overload");
    }
 
    void show(Lesson value) {
        System.out.println("Lesson overload");
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        LessonPrinter printer = new LessonPrinter();
        Lesson lesson = new Lesson();
        Object savedLesson = lesson;
 
        printer.show(lesson);
        printer.show(savedLesson);
        printer.show(null);
        printer.show((Object) null);
        printer.show((Lesson) null);
    }
}

Output:

Lesson overload
Object overload
Lesson overload
Object overload
Lesson overload

A Lesson argument selects show(Lesson). An Object reference selects show(Object). Plain null selects show(Lesson) because Lesson is more specific than Object. Casting null gives the argument a type and makes the intended overload clear.

If only show(Lesson) existed, passing savedLesson would not compile without a cast. Casting a non-null Object to Lesson succeeds only if the object is a Lesson or one of its subtypes; otherwise, it throws ClassCastException.

Example 6: Mixed Calls and an Ambiguous null Argument

class Lesson {
}
 
class LessonPrinter {
    void show(Object value) {
        System.out.println("Object overload");
    }
 
    void show(String value) {
        System.out.println("String overload");
    }
 
    void show(Lesson value) {
        System.out.println("Lesson overload");
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        LessonPrinter printer = new LessonPrinter();
        Object savedTitle = "Java methods";
        Object savedLesson = new Lesson();
 
        printer.show("Java methods");
        printer.show(new Lesson());
        printer.show(savedTitle);
        printer.show(savedLesson);
        printer.show((String) null);
        printer.show((Lesson) null);
        printer.show((Object) null);
 
        // Uncomment this line to see an ambiguous-call error:
        // printer.show(null);
    }
}

Output:

String overload
Lesson overload
Object overload
Object overload
String overload
Lesson overload
Object overload

Plain null can match Object, String, and Lesson. String and Lesson are both more specific than Object, but they are unrelated to each other. Java cannot choose between them, so printer.show(null) fails to compile. Adding show(Object) does not remove the ambiguity.

Use a typed variable or a cast, such as (String) null or (Lesson) null, to select the intended overload. The output above is for the program with the ambiguous call commented out.

Important Points About Type Promotion

  • Java can automatically convert primitive arguments using the rules below.
Argument typeCan automatically convert to
byteshort, int, long, float, double
shortint, long, float, double
charint, long, float, double
intlong, float, double
longfloat, double
floatdouble
doubleNo wider primitive type
booleanNo numeric type

The promotion paths are:

byte -> short -> int -> long -> float -> double
char -> int -> long -> float -> double
  • Java can skip steps. For example, byte can convert directly to long.
  • char cannot automatically convert to byte or short. byte and short cannot automatically convert to char.
  • boolean cannot convert to or from numeric types.
  • Converting int to float, or long to float or double, may round the value.
  • Java does not automatically narrow a double argument to int or long for a method call. If only show(long) existed, passing 18.5 would cause a compilation error.
  • Widening does not guarantee that every overloaded call has one best match. If no unique most specific method exists, the compiler reports an ambiguous call.
  • Overload resolution also has rules for boxing and variable arguments. Java first considers applicable fixed-argument methods without boxing or unboxing, then allows boxing and unboxing, and finally considers variable-argument calls.

Can We Overload a Method by Changing Only the Return Type?

No.

The return type alone cannot be used to overload a method.

This example intentionally does not compile:

class ScoreTotal {
 
    int add(int a, int b) {
        return a + b;
    }
 
    double add(int a, int b) {
        return a + b;
    }
}

Both methods have the same method signature:

add(int, int)

Only the return type is different.

Therefore, the compiler will report an error.

Method Overloading and static

Static methods can also be overloaded.

class ScoreTotal {
 
    static void printTotal(int a, int b) {
        System.out.println(a + b);
    }
 
    static void printTotal(int a, int b, int c) {
        System.out.println(a + b + c);
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        ScoreTotal.printTotal(8, 17);
        ScoreTotal.printTotal(8, 17, 25);
    }
}

Both methods are valid overloaded methods.

Method Overloading and Constructors

Constructors can also be overloaded.

class Member {
 
    Member() {
        System.out.println("Default constructor");
    }
 
    Member(String name) {
        System.out.println("Member: " + name);
    }
 
    Member(String name, int age) {
        System.out.println(name + " " + age);
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        new Member();
        new Member("Mira");
        new Member("Mira", 24);
    }
}

This is called constructor overloading.

Advantages of Method Overloading

1. Improves readability

The same method name can represent the same logical operation.

class ScoreTotal {
    int add(int a, int b) {
        return a + b;
    }
 
    int add(int a, int b, int c) {
        return a + b + c;
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        ScoreTotal scoreTotal = new ScoreTotal();
        System.out.println(scoreTotal.add(8, 17));
        System.out.println(scoreTotal.add(8, 17, 25));
    }
}

2. Provides flexibility

The caller can provide different types or numbers of arguments.

3. Reduces unnecessary method names

Instead of:

addTwoNumber()
addThreeNumber()

we can use one name, add, with different parameter lists.

4. Supports compile-time polymorphism

Method overloading is commonly known as compile-time polymorphism because the compiler determines which overloaded method should be called.

Method Overriding in Java

What is Method Overriding?

Method overriding occurs when a child class provides its own implementation of a method that is already defined in its parent class.

The method in the child class must have the same method signature as the parent method.

For example:

class Transport {//parent class
 
    void start() {//method in parent class
        System.out.println("Transport starts");
    }
}
 
//child class
class Shuttle extends Transport {
 
    @Override
    void start() {//method in child class
        System.out.println("Shuttle starts with an access card");
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        Transport transport = new Shuttle();
        transport.start();
    }
}

Here, Transport has a start() method.

Shuttle inherits that method but provides its own implementation.

Therefore, Shuttle overrides the start() method and has its own specific behavior.

Why Do We Need Method Overriding?

Suppose we have a general Transport class:

class Transport {
 
    void start() {
        System.out.println("Transport starts");
    }
}

Different vehicles may start differently.

A shuttle may start with an access card:

class Transport {
    void start() {
        System.out.println("Transport starts");
    }
}
 
class Shuttle extends Transport {
 
    @Override
    void start() {
        System.out.println("Shuttle starts with an access card");
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        Transport transport = new Shuttle();
        transport.start();
    }
}

A scooter may start using an ignition switch:

class Transport {
    void start() {
        System.out.println("Transport starts");
    }
}
 
class Scooter extends Transport {
 
    @Override
    void start() {
        System.out.println("Scooter starts with an ignition switch");
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        Transport transport = new Scooter();
        transport.start();
    }
}

The parent defines the common method:

start()

Each child class provides its own implementation.

Complete Example of Method Overriding

class Transport {
 
    void start() {
        System.out.println("Transport starts");
    }
}
 
class Shuttle extends Transport {
 
    @Override
    void start() {
        System.out.println("Shuttle starts with an access card");
    }
}
 
class Scooter extends Transport {
 
    @Override
    void start() {
        System.out.println("Scooter starts with an ignition switch");
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Transport shuttle = new Shuttle();
        shuttle.start();
 
        Transport scooter = new Scooter();
        scooter.start();
    }
}

Output

Shuttle starts with an access card
Scooter starts with an ignition switch

Notice:

class Transport {
    void start() {
        System.out.println("Transport starts");
    }
}
 
class Shuttle extends Transport {
    @Override
    void start() {
        System.out.println("Shuttle starts with an access card");
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        Transport shuttle = new Shuttle();
    }
}

The reference type is Transport, but the actual object is Shuttle.

When we call:

class Transport {
    void start() {
        System.out.println("Transport starts");
    }
}
 
class Shuttle extends Transport {
    @Override
    void start() {
        System.out.println("Shuttle starts with an access card");
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        Transport shuttle = new Shuttle();
        shuttle.start();
    }
}

Java executes the Shuttle implementation.

This is called runtime polymorphism or dynamic method dispatch.

Rules of Method Overriding

There are several important rules to remember.

1. Method name must be the same

Parent:

void start()

Child:

void start()

2. Parameter list must be the same

Parent:

void start(int speed)

Child:

void start(int speed)

This is overriding.

But:

void start(double speed)

is not overriding. It is a different method.

3. Return type must be the same or covariant

For example:

class Transport {
 
    Transport getTransport() {
        return this;
    }
}
 
class Shuttle extends Transport {
 
    @Override
    Shuttle getTransport() {
        return this;
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        Shuttle shuttle = new Shuttle();
        Shuttle result = shuttle.getTransport();
        System.out.println(result == shuttle); // true: the method returns the same object.
    }
}

Shuttle is a subtype of Transport, so this is allowed.

4. Access level cannot be more restrictive

For example, if the parent method is:

class BaseReporter {
 
    public void display() {
        System.out.println("BaseReporter");
    }
}

The following child declaration intentionally does not compile:

class BaseReporter {
    public void display() {
    }
}
 
class DetailedReporter extends BaseReporter {
    @Override
    private void display() { // Does not compile: cannot reduce public access.
    }
}

The child cannot reduce the visibility of the inherited method.

@Override Annotation

Java provides the @Override annotation to indicate that a method is intended to override a parent method.

class Transport {
    void start() {
        System.out.println("Transport starts");
    }
}
 
class Shuttle extends Transport {
 
    @Override
    void start() {
        System.out.println("Shuttle starts");
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        Transport transport = new Shuttle();
        transport.start();
    }
}

Using @Override is recommended because the compiler can detect mistakes.

This example intentionally does not compile because the method name is wrong:

class Transport {
    void start() {
        System.out.println("Transport starts");
    }
}
 
class Shuttle extends Transport {
    @Override
    void starts() { // Does not compile: Transport declares start(), not starts().
    }
}

the compiler will report an error because starts() does not override the parent's start() method.

Can Static Methods Be Overridden?

No.

Static methods belong to the class rather than the object.

If a child class defines a static method with the same signature as the parent, it is called method hiding, not method overriding.

class BaseReporter {
 
    static void display() {
        System.out.println("BaseReporter");
    }
}
 
class DetailedReporter extends BaseReporter {
 
    static void display() {
        System.out.println("DetailedReporter");
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        BaseReporter.display();
        DetailedReporter.display();
    }
}

This is method hiding.

Can Final Methods Be Overridden?

No.

A method declared as final cannot be overridden.

class Transport {
 
    final void stop() {
        System.out.println("Transport stopped");
    }
}

The following child declaration intentionally does not compile:

class Transport {
    final void stop() {
        System.out.println("Transport stopped");
    }
}
 
class Shuttle extends Transport {
 
    // ❌ Cannot override final method
    void stop() {
        System.out.println("Shuttle stopped");
    }
}

Can Private Methods Be Overridden?

No.

A private method is not inherited by the child class, so it cannot be overridden.

class BaseReporter {
 
    private void display() {
        System.out.println("BaseReporter");
    }
}

If the child defines a method with the same name:

class BaseReporter {
    private void display() {
        System.out.println("BaseReporter");
    }
}
 
class DetailedReporter extends BaseReporter {
 
    void display() {
        System.out.println("DetailedReporter");
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        DetailedReporter reporter = new DetailedReporter();
        reporter.display();
    }
}

this is a new method, not an overridden method.

Overloading vs Overriding

The two concepts can be distinguished easily.

FeatureMethod OverloadingMethod Overriding
MeaningSame method name with different parametersChild provides a new implementation of parent method
ClassesUsually within the same classRequires parent-child relationship
ParametersMust be differentMust be the same
Return typeCan be different, but cannot be the only differenceSame or covariant
PolymorphismCompile-time polymorphismRuntime polymorphism
Inheritance requiredNoYes
static methodsCan be overloadedCannot be overridden
final methodsCan be overloadedCannot be overridden
private methodsCan be overloadedCannot be overridden

Simple Difference

Method Overloading

class ScoreTotal {
 
    void add(int a, int b) {
    }
 
    void add(int a, int b, int c) {
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        ScoreTotal scores = new ScoreTotal();
        scores.add(8, 17);
        scores.add(8, 17, 25);
    }
}

Same class → Same method name → Different parameters

add(int, int)
add(int, int, int)

Method Overriding

class Transport {
 
    void start() {
    }
}
 
class Shuttle extends Transport {
 
    @Override
    void start() {
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        Transport transport = new Shuttle();
        transport.start();
    }
}

Parent class → Child class → Same method signature → Different implementation

Real-World Example

Consider a mobile phone.

Different phones can have a common operation:

void call();

But each phone may implement the operation differently.

class Phone {
 
    void call() {
        System.out.println("Making a call");
    }
}
 
class DeskPhone extends Phone {
 
    @Override
    void call() {
        System.out.println("Calling using a desk phone");
    }
}
 
class SatellitePhone extends Phone {
 
    @Override
    void call() {
        System.out.println("Calling using a satellite phone");
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        Phone desk = new DeskPhone();
        Phone satellite = new SatellitePhone();
        desk.call();
        satellite.call();
    }
}

Here, DeskPhone and SatellitePhone override the call() method.

Overloading Example from Real Life

Imagine a person can search using different types of input:

class LessonSearch {
 
    void search(String keyword) {
        System.out.println("Searching by keyword");
    }
 
    void search(String keyword, int page) {
        System.out.println("Searching by keyword and page");
    }
 
    void search(String keyword, String category) {
        System.out.println("Searching by keyword and category");
    }
}
 
 
public class HelloWorld {
    public static void main(String[] args) {
        LessonSearch lessons = new LessonSearch();
        lessons.search("methods");
        lessons.search("methods", 2);
        lessons.search("methods", "Java");
    }
}

The operation is conceptually the same:

search()

but it accepts different parameters.

This is method overloading.

How Overloading and Overriding Relate to Polymorphism

Polymorphism means one name can have multiple forms or behaviors.

These examples show two forms of polymorphism:

Polymorphism
     |
     ├── Method Overloading
     |       ↓
     |   Compile-time
     |   polymorphism
     |
     └── Method Overriding
             ↓
         Runtime
         polymorphism

Overloading

The compiler determines which method to call based on the arguments.

class ScoreTotal {
    int add(int a, int b) {
        return a + b;
    }
 
    int add(int a, int b, int c) {
        return a + b + c;
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        ScoreTotal scoreTotal = new ScoreTotal();
        System.out.println(scoreTotal.add(8, 17));
        System.out.println(scoreTotal.add(8, 17, 25));
    }
}

Overriding

The method implementation is determined based on the actual object at runtime.

class Transport {
    void start() {
        System.out.println("Transport starts");
    }
}
 
class Shuttle extends Transport {
    @Override
    void start() {
        System.out.println("Shuttle starts with an access card");
    }
}
 
public class HelloWorld {
    public static void main(String[] args) {
        Transport transport = new Shuttle();
 
        transport.start();
    }
}

The actual object is Shuttle, so the Shuttle implementation is executed.

Final Thoughts

Method Overloading

Method overloading allows a class to have multiple methods with the same name but different parameter lists.

Same name + Different parameters
              ↓
          Overloading
              ↓
      Compile-time polymorphism

Method Overriding

Method overriding allows a child class to provide its own implementation of a method inherited from its parent class.

Parent method
     ↓
Child provides new implementation
     ↓
      Overriding
     ↓
 Runtime polymorphism

Easy way to remember

  • Overloading → Same class, different parameters
  • Overriding → Parent and child, same method signature

See you in next page....🙂

← Java super keywordOverview →
← Java super keywordOverview →