Hello! Welcome to your fifth lesson in our module on OOP Foundations.
In the last lesson, we explored runtime polymorphism, which is achieved through method overriding. We saw how a parent class reference can point to a child class object, and the Java Virtual Machine (JVM) dynamically chooses the correct overridden method at runtime. This is a powerful feature for creating flexible and extensible systems.
Today, we will complete your understanding of polymorphism by focusing on this lesson's learning outcome: to differentiate compile-time polymorphism (method overloading) from runtime polymorphism (method overriding). We'll explore what method overloading is, how it works, and then draw a clear line between these two fundamental concepts. This distinction is a frequent topic in technical interviews, so mastering it is essential for your preparation.
1. The Other Side of Polymorphism: Method Overloading
While method overriding allows different classes in an inheritance hierarchy to provide their own implementation of a method, method overloading allows a single class to have multiple methods with the same name, as long as they have different parameters.
This is considered a form of polymorphism because the "form" of the method call—the arguments you provide—determines which implementation is executed.
To see this in action, let's watch a short segment from the 'Coding with John' video you saw in the previous lesson.
Java Polymorphism Fully Explained In 7 Minutes
This segment introduces method overloading. It contrasts it with the overriding concept you've already learned and shows a simple example of an eat method being overloaded in the Dog class.
Watch the video from 05:10 to 06:49. Focus on how a new eat method is created with the same name but a different parameter list within the same class.
As the video showed, the key to method overloading is the parameter list. You can overload a method by changing:
- The number of parameters.
- The type of parameters.
- The order of parameters.
Crucially, you cannot overload a method by only changing its return type. The compiler wouldn't know which method to call.
Because the compiler can determine exactly which method to execute based on the arguments you provide in your code, this process is resolved at compile-time. This is why method overloading is also known as compile-time polymorphism or static binding.
2. Overloading vs. Overriding: A Detailed Comparison
Now that we have introduced both concepts, let's dive deep into their differences. Understanding these distinctions is critical for interviews. The following video provides a very thorough, point-by-point comparison from an interview perspective.
Difference between Overloading and Overriding (part-II)
This video from DURGA EDUCATION is an excellent resource that systematically compares method overloading and overriding across several key criteria. It's dense with information that is highly relevant for a Java developer preparing for interviews.
Watch the video, paying close attention to the tabular comparison. Focus on these key points of difference: Method Signature (01:05 - 03:24): How names and arguments differ. Return Type (03:24 - 06:08): The rules for return types, including covariant types. private, static, and final methods (06:08 - 07:29): Which can be overloaded vs. overridden. Access Modifiers (07:29 - 09:44): The different rules for visibility. Method Resolution & Binding (11:55 - 15:04): This is the most important part. Understand who (Compiler vs. JVM) resolves the method call and when (compile-time vs. runtime).
To consolidate what you've just watched, here is a summary table and a visual comparison.
Summary Table
| Aspect | Method Overloading (Compile-Time Polymorphism) | Method Overriding (Runtime Polymorphism) |
|---|---|---|
| Purpose | To add more than one way to perform a similar action (convenience). | To provide a specific implementation of an inherited method (specialization). |
| Relationship | Occurs within the same class. | Occurs between a parent class and a child class (inheritance). |
| Method Signature | Same name, but different parameters (number, type, or order). | Same name and exactly the same parameters. |
| Binding Time | Compile-time (Static or Early Binding). The compiler decides. | Runtime (Dynamic or Late Binding). The JVM decides. |
| Return Type | Can be different. No restrictions. | Must be the same or a covariant type (a subtype of the parent's return type). |
| Access Modifier | No restrictions. Can be changed freely. | Cannot be more restrictive than the parent method (e.g., protected -> public is OK). |
static methods |
Can be overloaded. | Cannot be overridden. This is called method hiding. |
private methods |
Can be overloaded. | Cannot be overridden because they are not inherited. |
final methods |
Can be overloaded. | Cannot be overridden. |
Visual Comparison
This image provides a simple visual summary of the structural difference between the two concepts.

3. Key Interview Questions
Your understanding of this topic will almost certainly be tested in a Java LLD interview. Let's review some common questions.
Overloading vs Overriding in Java: Differences, Examples ...
The article 'Overloading vs Overriding in Java' from Index.dev has a great section dedicated to common interview questions. Reviewing them will help you solidify your knowledge.
Read the section titled 'Method Overloading and Method Overriding: Interview Questions'. Pay attention not just to the answers, but the reasoning behind them.
Here are the key questions distilled from the reading:
-
Can we override static methods?
No. A static method with the same signature in a subclass hides the parent's method, but it is not overriding. The method that gets called is determined by the reference type at compile-time, not the object type at runtime. -
Can constructors be overloaded or overridden?
Constructors can be overloaded (it's very common to provide multiple ways to create an object). They cannot be overridden because they are not inherited by subclasses. -
What is the difference between early (static) and late (dynamic) binding?
- Early Binding (Static): Happens at compile-time. The compiler links a method call to a specific method body. This is used for
private,final,staticmethods, and overloaded methods. - Late Binding (Dynamic): Happens at runtime. The JVM determines the method body to be executed based on the actual object type. This is used for overridden methods.
- Early Binding (Static): Happens at compile-time. The compiler links a method call to a specific method body. This is used for
Test your understanding!
Consider the following Java code. Identify which methods are examples of valid overriding, valid overloading, method hiding, or are simply invalid.
class Vehicle {
public void move() {
System.out.println("Vehicle is moving");
}
public static void stop() {
System.out.println("Vehicle has stopped");
}
}
class Car extends Vehicle {
// Method 1
@Override
public void move() {
System.out.println("Car is driving");
}
// Method 2
public void move(int speed) {
System.out.println("Car is driving at " + speed + " km/h");
}
// Method 3
public static void stop() {
System.out.println("Car has applied brakes");
}
// Method 4
// private void move() { }
}
What does Method 4 represent if it were uncommented?
Show answer
- Method 1 (
move()): This is a valid example of method overriding. It has the same signature as themove()method in theVehicleclass and uses the@Overrideannotation. - Method 2 (
move(int speed)): This is a valid example of method overloading. It is in theCarclass and has the same name asMethod 1but a different parameter list. - Method 3 (
stop()): This is an example of method hiding, not overriding. Because thestop()method isstaticin both the parent and child class, the method called depends on the compile-time reference type. - Method 4 (
private void move()): If this method were uncommented, it would cause a compile-time error. You cannot override a method and make it more restrictive. The parentmove()ispublic, andprivateis more restrictive.
Conclusion
You have now covered both forms of polymorphism in Java. Understanding their distinct mechanisms and purposes is fundamental to object-oriented design.
Key Takeaways:
- Method Overloading is compile-time polymorphism (static binding). It's about providing multiple methods with the same name but different parameters within the same class for convenience.
- Method Overriding is runtime polymorphism (dynamic binding). It's about a subclass providing a specific implementation for a method defined in its superclass, requiring an identical signature.
- The choice between them is driven by purpose: overloading for flexibility in how a method is called, and overriding for flexibility in how an action is performed across a type hierarchy.
In our next lesson, we will shift our focus to a critical part of an object's life cycle. We will explain the role of constructors in object instantiation and initialization, a topic where you will see method overloading used frequently.