Overloading vs Overriding in Java
Learn via video course

Overview
Method overloading in Java refers to the ability to define multiple methods with the same name but different parameters within the same class.
Method overriding in Java refers to the ability of a subclass to provide a specific implementation of a method that is already defined in its superclass. It allows a subclass to modify the behavior of an inherited method from its superclass.
Method overloading in Java allows multiple methods with the same name but different parameters in a class, while method overriding allows a subclass to provide a specific implementation of a method already defined in its superclass.
Method overloading is determined at compile-time based on the number, type, and order of parameters, while method overriding is determined at runtime.
Scope
The article focuses on the following topics:
- Polymorphism in Java
- Method Overloading vs. Method Overriding
- Static Variable Storage Area
- Rules of Method Overloading
- Purpose of Method Overloading
- Method Overloading Example
- Rules of Method Overriding
- Purpose of Method Overriding
- Method Overriding Example
Introduction
Java is often considered as one of the best languages when we talk about object-oriented programming because of its various concepts and features like classes, objects, inheritance, etc. Polymorphism is one of the core and important concepts of the object-oriented programming paradigm that is supported by Java.
The word polymorphism simply means having many forms. In computer science, it can be inferred to the concept that different types of objects can be accessed through the same interface. Each of the different types can give its independent implementation of the said interface.
The main advantage of polymorphism is that it allows us to simplify the programming interface. We can define conventions that we can then reuse in class after class. For example, the List interface in the Java collection framework defines methods that are used by different implementation classes like ArrayList to define the functionality.
With polymorphism, we can write methods that can process a variety of different types of functionalities with the same name. This also helps us to achieve consistency in our code.
In Java, we have majorly two types of polymorphism as shown below. We’ll cover their details in later sections.
Difference Between: Overloading vs Overriding in Java
Basis | Method Overloading | Method Overriding |
---|---|---|
Definition | Method overloading is when two or more methods have the same name and different arguments | Method overriding is when a subclass modifies a method of superclass having the same signature |
Method Signature | The overloaded methods must have different method signatures. It means that the methods must differ in at least one of these: number of parameters, type of parameters, and order of parameters, but should have the same name | The overridden methods must have the same method signature. It means that method name, number of arguments, order of arguments, and type of arguments should be an exact match |
Return Type | The return type of overloaded methods may or may not have the same return type | If the base class method has a primitive data type, then the overridden method of the subclass must have the same data type.But if the base class method has a derived return type, then the overridden method of the subclass must have either the same data type or subclass of the derived data type. |
Access Modifier | We do not have any restriction on access modifiers and may use any access modifier in the overloaded method | The overridden method in subclass should have the same or less restricted access modifier |
Binding | The method call is binded to method definition at compile time. Also known as Static Binding. | The method call is binded to method definition at compile time. Also known as Dynamic Binding. |
Polymorphism Type | It is an application of compile-time polymorphism | It is an application of run-time polymorphism |
Scope | The overloading functions always exist in the same scope | The overriding function always exists in different scope |
Purpose | Gives functionality to allow different methods to have the same name and act differently based on the parameters supplied to them | Gives functionality to add some extra or unexpected functionality in the subclass as compared to the superclass |
Inheritance Scope | Doesn't need inheritance, can be performed within the same class | Relies on inheritance, occurs in classes depicting is-a (parent-child) relationship |
Private Methods | Can be overloaded | Cannot be overridden |
Final Methods | Can be overloaded | Cannot be overridden |
Static Methods | Can be overloaded | Cannot be overridden |
Error Handling | If overloading breaks, we get a compile-time error which is relatively easy to fix | If overriding breaks, we get run-time errors which are more serious and relatively more complex to fix. |
Usage | We can overload methods any number of times in a class | We can override a method only one time in an inheriting class |
What is Method Overloading?
Method overloading in Java refers to the concept where more than one method shares the same method name and has a different parameters list in the same class. With the use of method overloading, we can define methods that do similar tasks under the same name.
Method overloading is an example of compile-time polymorphism, static or early binding. Compile-time polymorphism is when we bind an object with its functionality at compile-time only. In Java, the JVM knows before executing the code which method or object it is going to execute for a particular call.
Rules of Method Overloading
To overload methods in Java, we can change one or more of the following:
- The function name
- The type of parameters
- The order of parameters
Why Method Overloading?
Let’s take an example to understand why we need method overloading. Suppose, we have a problem where we want to perform addition on different types (float, int, double, etc) and different counts of numbers.
When trying to solve this problem in Java, we make a class Addition that will have different methods for different types of addition. Without method overloading, we’d have to create methods with different names like addTwoIntegers(), addIntegerAndFloat(), etc. as shown in the diagram below:
Let’s see how method overloading can help us to solve the above problem by overloading a simple add() method:
In the above diagram, we are overloading the add() method by passing different type, order, and number of arguments. We’ll see the full code of this example in the next section.
In method overloading, the return type can or cannot be the same, but we must change the parameters list because, in Java, we cannot achieve method overloading by changing only the return type of the method. The reason behind this is that it causes ambiguity as, for two methods having the same parameters list, the JVM cannot decide which method to call as we cannot know the return type before execution of the method.
The following rules must be obeyed while method overloading:
- Return types cannot be overloaded
- We cannot overload two methods by just a static keyword, we can only overload them if their parameters list is different
- We can overload Java’s main() method but JVM will call the main method having an array of string arguments
Example of Method Overloading
Let’s try to solve the above problem with the help of a code example of method overloading in Java. We will implement the above solution of overloading the add() method of the Addition class. This class will perform addition according to the type, number, and order of arguments it receives.
If we run the above code, we’ll get the following output:
Output:
Explanation:
Now, as we can see, we have called add() with different combinations of parameters, and each time the JVM automatically calls the required method. This is how we can do method overloading.
Also if we are using an IDE and do “ctrl+click” on any of add() methods in the main() function, we’ll see that it takes us to the function it is going to call while execution. This shows that before running our code, JVM already knows which method to execute for a call. This is why it is also called compile-time polymorphism.
What is Method Overriding?
Method overriding is simply redefining a function of a superclass in the subclass with the same method signature. The same signature means the methods must have the same name, the same number of parameters, and the same type of parameters in the same sequence. It is used to change the behavior of existing methods, to provide fine-grained implementations in subclasses for methods defined in a superclass.
Rules of Method Overriding
The following rules must be obeyed while method overriding:
- Method overriding can only be implemented when two classes have an ‘is-a’ relationship of inheritance between them.
- The return type of the overridden method must be the same or covariant of the return type of the superclass method.
For example, in the following code snippet, we can see that the return type of overriding method countIntegers() is Integer which is a subtype of the return type of overridden method countNumbers() that is Number.
Explanation:
The provided Java code snippet demonstrates an example of method overriding. Here's a breakdown of the code:
- The NumbersBucket class serves as the superclass, and it declares a method named countNumbers() that returns a Number type.
- The IntegersBucket class extends the NumbersBucket class, indicating an "is-a" relationship. This means that IntegersBucket is a subclass of NumbersBucket.
- The IntegersBucket class overrides the countNumbers() method from the superclass using the @Override annotation. The overridden method in the IntegersBucket class is named countIntegers(), and it returns an Integer type.
Additional Points on Method Overriding
- It can’t have a more restrictive access modifier. For example, if the parent’s method is protected, then the child’s overridden method cannot be private.
- @Override annotation may or may not be used on the overridden methods, but using this annotation can help us identify if we are not obeying any overriding rules as we get a compile-time error if we are not properly overriding the method annotated with @Override annotation. But in case the method is not annotated with @Override annotation, then if the method is not obeying overriding rules, the JVM treats the method as a new method.
- Only inherited methods can be overridden in the subclass. Constructors and private methods cannot be overridden as they’re not inherited. We must override the abstract methods in the first concrete i.e non-abstract subclass. Final and static methods cannot be overridden, only instance methods are overridden.
- We can also call the superclass method in the subclass using the super keyword, to get the superclass version of an overridden method.
Method overriding is an example of run-time polymorphism, dynamic or late binding. It is also known as Dynamic Method Dispatch because the method that is going to be called is decided at run time by the JVM.
Why Method Overriding?
Let’s take an example to understand why we need method overriding.
Let’s say we want to model a scenario where we had a class Train having three basic methods, start(), stop(), and accelerate(). Now, we have a situation where we want to have another class BulletTrain that does everything that the Train class does but accelerates with a higher speed.
As we know, the best thing for us to do in this case is to inherit the BulletTrain class from the Train class. Now, if there was no method overriding, we would have to create a different method that would provide the implementation for faster acceleration in the BulletTrain class, say accelerateFast(). This is where method overriding comes into the picture and helps us change the implementation of a method from the base class in the subclass.
Let’s see how overriding methods helps us solve the above problem with the help of the following diagram:
In the diagram above, we’ve simply overridden the accelerate() method of the Train class to provide a more refined implementation for the subclass BulletTrain. We’ll see the full code of this example in the next section.
Example of Method Overriding
Let’s try to solve the above problem with the help of a code example of method overriding in Java. We’ll override the accelerate() method in the BulletTrain subclass to give a more refined implementation.
Output:
Explanation:
- The Train class is defined with three methods: accelerate(), start(), and stop(). Each method returns a string representing the action performed.
- The BulletTrain class extends the Train class and overrides all three methods using the @Override annotation. The overridden methods provide specialized implementations for the BulletTrain class.
- The Example class contains the main() method, where instances of both Train and BulletTrain are created and used to invoke the overridden methods.
- In the main() method, a Train object is created, and its start(), accelerate(), and stop() methods are called. The output of these method invocations is printed.
- Next, a BulletTrain object is created and assigned to a Train reference. This demonstrates polymorphism, as a subclass object can be assigned to a superclass reference.
- The overridden methods in the BulletTrain class are invoked using the bulletTrain reference. The output of these method invocations is also printed.
Conclusion
-
Method Overriding: Method overriding is the process of redefining a method in a subclass that is already defined in its superclass. It allows the subclass to provide its own implementation for an inherited method, modifying or extending its behavior while maintaining the same method signature.
-
Rules of Method Overriding: Several rules govern method overriding:
- The overriding method must have the same method name, number of parameters, and types of parameters as the overridden method.
- The return type of the overriding method must be the same or a subtype (covariant) of the return type in the superclass.
- The access modifier of the overriding method cannot be more restrictive than the access modifier of the overridden method.
- Only inherited methods can be overridden, not private methods or constructors.
- The @Override annotation, while optional, is highly recommended to ensure proper overriding and detect errors at compile-time.
-
Inheritance: Method overriding relies on the concept of inheritance, where a subclass extends or inherits from a superclass. This "is-a" relationship allows the subclass to inherit the methods and attributes of the superclass and override methods when needed.
-
Polymorphism: Method overriding is a key aspect of polymorphism, which allows objects of different classes to be treated as objects of a common superclass. Polymorphism enables code reuse and flexibility, as superclass references can be used to invoke overridden methods in subclasses.
-
Method Overloading: Method overloading is the process of defining multiple methods with the same name but different parameters within a class. It allows a class to have multiple methods with the same name but different behaviors based on the type, order, or number of parameters.
-
Rules of Method Overloading: Several rules govern method overloading:
- The overloaded methods must have the same name but different parameter lists.
- The parameters can differ in their types, order, or number.
- The return type of the method is not considered when overloading a method.
- Overloaded methods may have different access modifiers.
-
Signature of a Method: The signature of a method consists of its name and the parameter list. Overloading is determined by comparing the method signatures.
-
Compile-time Resolution: During compilation, the Java compiler resolves which overloaded method to call based on the arguments provided and the method signatures. The appropriate method is determined based on the most specific matching parameters.
-
Benefits of Method Overloading: Method overloading provides several benefits, including:
- Improved code readability and maintainability by using intuitive and self-descriptive method names.
- Flexibility in accepting different types and numbers of arguments without needing to create multiple method names.
- Code reuse by providing different implementations of a method based on different parameter combinations.
- Avoidance of naming conflicts by using the same method name but with different parameters.