Overloading vs Overriding in Java

Challenge Inside! : Find out where you stand! Try quiz, solve problems & win rewards!

Learn via video course

Java Course - Mastering the Fundamentals
Java Course - Mastering the Fundamentals
By Tarun Luthra
Free
star5
Enrolled: 1000
Java Course - Mastering the Fundamentals
Java Course - Mastering the Fundamentals
Tarun Luthra
Free
5
icon_usercirclecheck-01Enrolled: 1000
Start Learning

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.

two types of polymorphism in java

Difference Between: Overloading vs Overriding in Java

BasisMethod OverloadingMethod Overriding
DefinitionMethod overloading is when two or more methods have the same name and different argumentsMethod overriding is when a subclass modifies a method of superclass having the same signature
Method SignatureThe 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 nameThe 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 TypeThe return type of overloaded methods may or may not have the same return typeIf 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 ModifierWe do not have any restriction on access modifiers and may use any access modifier in the overloaded methodThe overridden method in subclass should have the same or less restricted access modifier
BindingThe 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 TypeIt is an application of compile-time polymorphismIt is an application of run-time polymorphism
ScopeThe overloading functions always exist in the same scopeThe overriding function always exists in different scope
PurposeGives functionality to allow different methods to have the same name and act differently based on the parameters supplied to themGives functionality to add some extra or unexpected functionality in the subclass as compared to the superclass
Inheritance ScopeDoesn't need inheritance, can be performed within the same classRelies on inheritance, occurs in classes depicting is-a (parent-child) relationship
Private MethodsCan be overloadedCannot be overridden
Final MethodsCan be overloadedCannot be overridden
Static MethodsCan be overloadedCannot be overridden
Error HandlingIf overloading breaks, we get a compile-time error which is relatively easy to fixIf overriding breaks, we get run-time errors which are more serious and relatively more complex to fix.
UsageWe can overload methods any number of times in a classWe 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:

why method overloading

Let’s see how method overloading can help us to solve the above problem by overloading a simple add() method:

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:

  1. The NumbersBucket class serves as the superclass, and it declares a method named countNumbers() that returns a Number type.
  2. The IntegersBucket class extends the NumbersBucket class, indicating an "is-a" relationship. This means that IntegersBucket is a subclass of NumbersBucket.
  3. 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:

overriding methods to solve problems

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:

  1. The Train class is defined with three methods: accelerate(), start(), and stop(). Each method returns a string representing the action performed.
  2. 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.
  3. The Example class contains the main() method, where instances of both Train and BulletTrain are created and used to invoke the overridden methods.
  4. 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.
  5. 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.
  6. The overridden methods in the BulletTrain class are invoked using the bulletTrain reference. The output of these method invocations is also printed.

Conclusion

  1. 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.

  2. 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.
  3. 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.

  4. 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.

  5. 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.

  6. 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.
  7. 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.

  8. 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.

  9. 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.