Method overriding in Java

Here is the table content of the article will we will cover this topic.
1. What is Method overriding in Java?
2. What are the Rules of
Method overriding in Java?
3. Can we override the final method in java?
4. Can we override the static method in java?
5. Covariant return type in java
6. Method overriding in Exception handling?

Video available in Hindi

What is Method overriding in Java?

In this article, we will discuss the method overriding in Java. To overload a method, we will read the different rules. You should read about the inheritance first if you have not read the inheritance yet. Because you should have basic knowledge of inheritance.

Method overriding in java is only possible with the concept of Inheritance. As you know by using of inheritance concept in Java, we can inherit the variables/methods of the parent class to the child class. Method overriding in Java is a feature through which we can define the method in the child class that is already defined in the parent class. If a method in a child class has the same name and parameters as a method defined in the parent class, then the method defined in the subclass is called an overriding method, and the method defined in the parent class is called an overridden method.

Whenever a child class extends a parent class, the child class automatically inherits all the methods defined in the parent class(Obviously private method doesn’t inherit). These methods are known as derived methods.
Java allows providing a specific implementation of a method in a child class.

method overriding in java

Let’s say a parent class has a method sum(int, int) and a child class provides the specific implementation of the method (sum(int, int)) that has been declared in the parent class. It is known as method overriding.

class ParentClass
{
   // Overridden method
   public void printData()
   {
      System.out.println("In this method we are showing the details of Parent class");
   }
}
class ChildClass extends ParentClass
{
  	 //Overriding method
	public void printData()
	{
	     System.out.println("In this method we are showing the details of child class");
	     System.out.println("We are overriding the method");
	}
   public static void main( String args[]) {
	   ParentClass parentObject = new ChildClass();
      //This will call the child class method
	   parentObject.printData();
   }
}

Output:
In this method we are showing the details of child class
We are overriding the method
Advantage of method overriding:

What are the rules for Method overriding in Java?

We will use two terms here one is an overriding method and overridden method. The method defined in the subclass is called an overriding method and the method defined in the parent class is called an overridden method.

1. Argument/Parameters list

While overriding the method in the child class we should take care of the method name, the number of parameters, and the type of parameters. The method name, number of parameters, and type of parameters should be as in the Parent class.
If you change anything in the arguments of the method of the child class, then it doesn’t consider method overriding.

2. covariant type

If you are using the earlier version of Java 5 then the return type must have the same override method and overridden method. From Java 5 onward, the return type can also be a subclass (subclasses are a covariant type to their parents).

3. Access modifier

The access level can’t be more restrictive than the overridden method’s access level. You can’t be more restrictive in the overridden method.

Example: If the Access Modifier of the overridden method (method of Parent class) is public then the overriding method (child class method ) cannot have a private, protected, and default Access modifier because all three access modifiers are more restrictive than public. We can read Access Modifier from here.

class ParentClass
{
   // Overridden method
   public void printData()
   {
      System.out.println("In this method we are showing the details of Parent class");
   }
}
class ChildClass extends ParentClass
{
  	 //Overriding method
	private void printData()
	{
	     System.out.println("In this method we are showing the details of child class");
	     System.out.println("We are overriding the method");
	}
   public static void main( String args[]) {
	   ChildClass childObject = new ChildClass();
      //This will call the child class method
	   childObject.printData();
   }
}

Output:
Exception in thread “main” java.lang.Error: Unresolved compilation problem: Cannot reduce the visibility of the inherited method from ParentClass at ChildClass.printData(ChildClass.java:12) at ChildClass.main(ChildClass.java:20)

4. Checked Exception handling

The overriding method can throw any unchecked exceptions, whether the overridden method is throwing any exceptions or not.

5. Checked Exception handling

The overriding method must not throw new or broader checked exceptions than the ones declared by the overridden method. You can read it in detail.

import java.io.IOException;
class ParentClass 
{  
   void color() throws IOException
   {
       System.out.println("Red");
   }  
}
class ChildClass extends ParentClass {
   //It throws a checked exception
   void color() throws IOException
   {
       System.out.println("White");
   }  
   public static void main(String args[]){  
     ParentClass obj = new ChildClass();  
       try 
       {
    obj. color();
       } 
       catch (IOException e) 
       {
    e.printStackTrace();
       } 
   } 
}

The code will run fine because the color() method of the Parent class and child class is throwing a checked exception and throwing an exception by the child class method should not superclass of exception thrown by the Parent class.

6. final methods can’t override

final keyword uses for restricting some functionalities. If we are declaring any method with the final keyword it means we can’t change its implementation in the child class. So, Java doesn’t permit the override of any final method. You can read it in detail.

Example:

  
class Parent 
{ 
    // final method in base class 
    final void showData() 
    { 
        System.out.println("This is Static method of Parent class"); 
    } 
} 
  
class Child extends Parent 
{ 
	// final method in drived class
    final void showData()
    { 
        System.out.println("This is Static method of child class"); 
    } 
} 
  
class MainClass { 
    public static void main(String[] args) 
    { 
        Parent parent = new Child(); 
        parent.showData();        
    } 
}

Output: The above example will show compilation error

7. static methods can’t override

If you have a static method in the Parent class and you define a static method with the same signature as a static method in the Parent class. In this case, the Child class method acts differently. It is known as method hiding. You can read it in detail.

  
class Parent 
{ 
    // Static method in base class 
    static void showData() 
    { 
        System.out.println("This is Static method of Parent class"); 
    } 
} 
  
class Child extends Parent 
{ 
	// static method in drived class
    static void showData()
    { 
        System.out.println("This is Static method of child class"); 
    } 
} 
  
class MainClass { 
    public static void main(String[] args) 
    { 
        Parent parent = new Child(); 
        parent.showData();      
    } 
}

Output: This is Static method of Parent class

As you know Static method can directly be called with the class name. In this example, we are calling the showData() method by reference to the Parent class then the compiler converts.

8. Private methods can’t override

Private methods cannot be overridden as they are local to the class. You can’t inherit the private variables and methods of the parent class.

class ParentClass
{
   private void printData()
   {
      System.out.println("In this method we are showing the details of Parent class");
   }
}
class ChildClass extends ParentClass
{
   //Overriding method
	private void printData()
	{
	     System.out.println("In this method we are showing the details of child class");
	     System.out.println("We are overriding the method");
	}
   public static void main( String args[]) {
	   ParentClass obj = new ChildClass();
      //This will call the child class method
	   obj.printData();
   }
}

Output: Exception in thread “main” java.lang.Error: Unresolved compilation problem:     The method printData() from the type ParentClass is not visible at ChildClass.main(ChildClass.java:19)

We get the compiler error printData() has private access in the Parent class. So the compiler tries to call the Parent class function, not the child class, which means printData() is not overridden.

9. If any method can’t be inherited then it can’t be overridden. It may be a scenario because the protected method is inherited within the package.

10. The abstract methods must be overridden by the first concrete subclass.

11. You can’t override the constructor of the parent class. Because the Constructor name must always be the same as the Class name.

Can we override the final method in java?

Most beginners have a common doubt can we override final method in java? We will resolve all the ambiguities and see how we can we override final method in java? If not, then what is the reason?

A method is declared with the final keyword, then it is known as the final method. The final method can’t be overridden. A final method declared in the Parent class can’t be overridden by a child class. If we try to override the final method,  the compiler will throw an exception at compile time. Because we are declaring any method with the final keyword and we are indicating the JVM to provide some special attention and make sure no one can override it. We will discuss the reason in detail.

class Student
{
	int rollNo;
	String className;
	String name;
	String fee;
	
	Student() 
	{}
	
	public Student(int rollNo, String className, String name, String fee) 
	{
		this.rollNo = rollNo;
		this.className = className;
		this.name = name;
		this.fee = fee;
	}
	
	public final void printData()
	{
		System.out.println("Name : " + name + ", RollNo: "+ rollNo + ", Class Name : "+ className);
		System.out.println("Fee details" + fee);
	}
	
	public void games()
	{
		System.out.println("Cricket, Hockey, Football");
	}
}

public class Record extends Student
{
	public final void printData()
	{
		System.out.println("Name : " + name + ", RollNo: "+ rollNo + ", Class Name : "+ className);
	}
	
	public void games()
	{
		System.out.println("Table tenis, Swimming");
	}
	
	public static void main(String arg[])
	{
		Student student = new Student(101, "MCA", "Ram", "10000");
		Record record = new Record();
		record.printData();
		record.games();
	}
}

Error: LinkageError occurred while loading main class create.Record java.lang.VerifyError: class create.Record overrides final method create.Student.printData()

can we override final method in java

Why we can’t override the final method?

As you know by use of the overriding concept, we can provide different implementations in child classes. But sometimes we want to provide only default implementation to each child class. We can prevent the overriding of the method by the use of the final keyword.  When we declare a method with the final keyword. It means we are preventing it so that any child class can’t override it. The final method indicates the JVM to apply these restrictions.
If any developer tries to override the final method the JVM shows the exception at compile time.

Can we override the static method in java?

The most common and tricky question in java, can we override static method? Before moving further I will recommend you please read the method overriding and static method in java. In this post, we will discuss whether can we override static method in java.
No, we can’t override the static method in java. If we declare a method with the same signature in the child class. It considered method hiding instead of method overriding.

In Java, we can declare a static method in the child class with the same signatures as in the Parent class. But it doesn’t consider the method overriding. The static method of the child class will hide the implementation of the method of the Parent class. It is known as method hiding. Because the compiler decides which method to execute at the compile time, not at the runtime. As you know the static method can be accessed by class name rather than the object. When the compiler invokes the static method then it accesses the static method of the child class.

can we override static method
class ParentClass 
{	
	public static void printData()
	{
		System.out.println("Method of Parent class");
	}
}

public class ChildClass extends ParentClass
{
	public static void printData()
	{
		System.out.println("Method  of Child class");
	}
	
	public static void main(String arg[])
	{
		// Here we are creating object of Parent class but static method always use class
		// So it will call the method of Parent class
		ParentClass parent = new ParentClass();
		parent.printData();
		
		// Here we are creating object of Child class but static method always use class
		// So it will call the method of Child class
		ChildClass child = new ChildClass();
		child.printData();
		
		// Here we are creating object of Child class and reference of Parent class
		// But static method always use the class name
		// So it will call the method of Parent class
		ParentClass childObject = new ChildClass();
		childObject.printData();
	}
}

Output: Method of Parent class
Method  of Child class
Method of Parent class

Covariant return type in java

Covariant method overriding is a powerful feature of Java that was introduced in Java 5. Many programmers don’t know about the covariant return type in java. We will discuss what Covariant method overriding is and how to implement it?

As we have already learned the method overriding. In method overriding we can define the method in the child class that is already defined in parent classes. Make sure the signature and return type must be the same. That was true only before Java 5.

In Java 5, The covariant return types are newly introduced. After introducing the covariant return type, Java allows us to change the return type of the overriding method(Method in child class). But the return type of the overriding method (Method of child class) must be a subtype of the overridden method (Method of Parent class). If you try to provide the return type of overriding method(Method of child class) with supertype, then it with throw exception at compile time.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class Student
{
	public ArrayList<String> listOfName()
	{
		ArrayList<String> listOfName = new ArrayList<String>();
		listOfName.add("John");
		listOfName.add("Ram");
		listOfName.add("Mary");
		
		return listOfName;
	}
}

public class Record extends Student
{
	public List<String> listOfName()
	{
		List<String> listOfName = new ArrayList<String>();
		listOfName.add("Java");
		listOfName.add("Goal");
		listOfName.add("WebSite");
	
		return listOfName;
	}
	public static void main(String arg[])
	{
		Record record = new Record();
		record.listOfName();
	}
}

Output: Exception in thread “main” java.lang.Error: Unresolved compilation problem: The return type is incompatible with Student.listOfName() at create.Record.listOfName(Record.java:22) at create.Record.main(Record.java:34)

In the above example, we have two classes Student(Parent class) and Record(Child class). The Record class inherits the method from the Student class. The Student class (Parent class) having the listOfName() method and its return type is ArrayList<String>. This method is automatically inherited in the Record class. In the Record class, we are overriding the listOfName() method but its return type is List<String>. This is not possible because List is the Parent of ArrayList.

We can return only the sub-type. Let’s see in below example:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class Student
{
	public List<String> listOfName()
	{
		ArrayList<String> listOfName = new ArrayList<String>();
		listOfName.add("John");
		listOfName.add("Ram");
		listOfName.add("Mary");
		
		return listOfName;
	}
}

public class Record extends Student
{
	public ArrayList<String> listOfName()
	{
		ArrayList<String> listOfName = new ArrayList<String>();
		listOfName.add("Java");
		listOfName.add("Goal");
		listOfName.add("WebSite");
	
		return listOfName;
	}
	public static void main(String arg[])
	{
		Record record = new Record();
		System.out.println(record.listOfName());
	}
}

Output: [Java, Goal, WebSite]

covariant return type in java

Advantage of covariant return type in java

The Covariant method overriding provides a way that you can return the subtype of the actual return type of overridden method. It helps the programmer to remove the burden of typecasting. This method mostly uses when the overriding method returns an object.

Let’s understand it with an example. You must have seen the working of clone() method in Java classes. If you are not familiar with the working of clone() method, then read it from here.

The clone() method returns the object of the Object class. But we can return the object of our own class because every class is the child of the Object class. Suppose the Covariant method overriding concept has not introduced yet. Then we need to cast the object every time.
Let’s see in example:

import java.util.ArrayList;
class Student implements Cloneable
{
	int rollNo;
	String className;
	String name;
	
	public int getRollNo() {
		return rollNo;
	}

	public void setRollNo(int rollNo) {
		this.rollNo = rollNo;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	
	public Student(int rollNo, String className, String name) 
	{
		this.rollNo = rollNo;
		this.className = className;
		this.name = name;
	}
	
	public void printData()
	{
		System.out.println("Name : " + name + ", RollNo: "+ rollNo + ", Class Name : "+ className);
	}

	@Override
	public Object clone() throws CloneNotSupportedException
	{
		return super.clone();
	}
}

public class MainClass
{
	public static void main(String arg[]) throws CloneNotSupportedException
	{
		Student student1 = new Student(1, "MCA", "Ram");
		student1.printData();
		
		Student student2 = (Student) student1.clone();
		student2.setName("Ravi");
		student2.setRollNo(2);
		student2.printData();
	}
}

Output: Name : Ram, RollNo: 1, Class Name : MCA
Name : Ravi, RollNo: 2, Class Name : MCA

In the above example when we are using the clone() method, it returns the object of Object class and then we typecast it into the Student class.

Student student2 = (Student) student1.clone();

Suppose we are using the clone method 10 times in the program then we need to typecast it every time. To overcome these types of problems we can Covariant method overriding. By using the Covariant concept, we can return the object of the Student class instead of the Object class.
Let’s see how we can use it.

import java.util.ArrayList;
class Student implements Cloneable
{
	int rollNo;
	String className;
	String name;
	
	public int getRollNo() {
		return rollNo;
	}

	public void setRollNo(int rollNo) {
		this.rollNo = rollNo;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	
	public Student(int rollNo, String className, String name) 
	{
		this.rollNo = rollNo;
		this.className = className;
		this.name = name;
	}
	
	public void printData()
	{
		System.out.println("Name : " + name + ", RollNo: "+ rollNo + ", Class Name : "+ className);
	}

	@Override
	public Student clone() throws CloneNotSupportedException
	{
		return (Student) super.clone();
	}
}

public class MainClass
{
	public static void main(String arg[]) throws CloneNotSupportedException
	{
		Student student1 = new Student(1, "MCA", "Ram");
		student1.printData();
		
		Student student2 = student1.clone();
		student2.setName("Ravi");
		student2.setRollNo(2);
		student2.printData();
	}
}

Output: Name : Ram, RollNo: 1, Class Name : MCA
Name : Ravi, RollNo: 2, Class Name : MCA

You can see above, we don’t need to typecast the object returned from the clone() method to Student, because we are returning an object of the Student class instead of the Object class.

Exception handling with Method overriding

Here are some rules of Exception handling with Method overriding. If you are overriding the method in the child class then you should take care of these scenarios. If you are not familiar with exception handling and method overriding, then you should read them first. Because these will help you to understand the rules here.

Scenario 1: If the parent class doesn’t throw any exception but the child class throws an unchecked exception

In this example, we have a Parent class and a child class having a method color(). The method of the Parent class is not throwing any exceptions. However, the overriding method of the Child class is throwing an unchecked exception (NullPointerException). This will run successfully.

class ParentClass 
{  
   void color()
   {
       System.out.println("Red");
   }  
}
class ChildClass extends ParentClass {
   //It throws an unchecked exception
   void color() throws NullPointerException
   {
       System.out.println("White");
   }  
   public static void main(String args[]){  
	   ParentClass obj = new ChildClass();  
       obj.color(); 
   } 
}

Output: White

Scenario 2:  If the parent class doesn’t throw any exception but the child class throws a checked exception

In this example, we have a Parent class and a child class having a method color(). The method of the Parent class is not throwing any exceptions. However, the overriding method of the Child class is throwing a checked exception (IOException). This will compile errors at compile time successfully. Because the overriding method (Child class method) can’t throw a checked exception if the overridden method(Parent class method) is not throwing an exception.

import java.io.IOException;

class ParentClass 
{  
   void color()
   {
       System.out.println("Red");
   }  
}
class ChildClass extends ParentClass {
   //It throws a checked exception
   void color() throws IOException
   {
       System.out.println("White");
   }  
   public static void main(String args[]){  
	   ParentClass obj = new ChildClass();  
       obj.color(); 
   } 
}

Output: Exception in thread “main” java.lang.Error: Unresolved compilation problem: Exception IOException is not compatible with throws clause in ParentClass.color() at ChildClass.color(ChildClass.java:12) at ChildClass.main(ChildClass.java:18)

Scenario 3: If parent class and child class both throws a checked exception

import java.io.IOException;

class ParentClass 
{  
   void color() throws IOException
   {
       System.out.println("Red");
   }  
}
class ChildClass extends ParentClass {
   //It throws a checked exception
   void color() throws IOException
   {
       System.out.println("White");
   }  
   public static void main(String args[]){  
	   ParentClass obj = new ChildClass();  
       try 
       {
		obj. color();
       } 
       catch (IOException e) 
       {
		e.printStackTrace();
       } 
   } 
}

The code will run fine because the color() method of the Parent class and child class is throwing a checked exception and throwing an exception by the child class method should not superclass of exception thrown by the Parent class.

Scenario 4: If the overriding method in a subclass throws its superclass exception

import java.io.IOException;

class ParentClass 
{  
   void color() throws IOException
   {
       System.out.println("Red");
   }  
}
class ChildClass extends ParentClass {
   //It throws a checked exception
   void color() throws Exception
   {
       System.out.println("White");
   }  
   public static void main(String args[]){  
	   ParentClass obj = new ChildClass();  
       try 
       {
		obj. color();
       } 
       catch (Exception e) 
       {
		e.printStackTrace();
       } 
   } 
}

Output:
Compilation error because the color() method of child class is throwing Exception which is super class of thrown by method color() of parent class.

Video available in Hindi