In this article, we will understand Java overriding concepts with respect to Java method signature i.e.
- Access modifier
- Return type (also, will look into co-variant return type)
- Exception handling
1. Java overriding:
While inheriting super class, if a sub class has a same instance method with same method signature as that of the super class’s method then it is said to be method overriding in Java.
Same method signature means, exactly same
- Method name
- Number of formal parameters (input parameters)
- Access modifier (or more wider/broader access modifier of overridden method)
- Return type (sub class or sub-type of overridden method’s return type)
- Checked exception (sub class or sub-type of overridden method’s exception)
Note: There is no restriction on un-checked exception, as overriding method in the sub class can throw any un-checked exceptions irrespective of the overridden method’s exception in throws clause
Reason to have another exactly same method in the inheriting class is to provide more specific implementation from that of more general implementation in super class
2. Java method signature:
- Instance method (non-static)
- Static method (class method)
We will concentrate only on instance method signature and list out limitations or rules w.r.t access modifier, return type and exception handling while overriding
2.1 Instance method (non-static):
Java method signature with access modifier, return type and throws clause (exception)
public int add(int number1, int number2) throws Exception {
return summation;
}
2.2 Diagrammatic representation of Instance method:
3. Example for Instance method
- Super class>> Shape (in.bench.resources.method.overriding)
- Overridden method>> draw()
- access modifier: public
- return type: void
- throws: Exception (java.lang.Exception)
- Sub class>> Circle (in.bench.resources.method.overriding)
- Extending Super class>> Shape (in.bench.resources.method.overriding)
- Overriding method>> draw()
- access modifier: public
- return type: void
- throws: Exception (java.lang.Exception)
In above example, method signature in the overriding method in sub class is exactly same as that of super class’s overridden method
But we can narrow/widen few things in Java method signature w.r.t below three things
- Access modifier
- Return type
- Exception
Let us understand widening & narrowing concept
4. Access modifier:
There are four types of access modifier in Java for defining access visibility (or to define scope) of
- member variable
- method
- constructor
- class
These four access modifiers are tabulated below,
Access modifier | Visibility/Accessibility |
private | visible/accessible only within class |
default | visible/accessible only inside the same package |
protected | visible/accessible within the package and all sub classes |
public | visible/accessible everywhere |
We will restrict the discussion to Java methods only;
While inheriting method from super class to a sub class, access level can be kept same or it should be wider/broader
Access level increases in below order (with private being the least and public being the highest)
- private
- default
- protected
- public
4.1 Example for widening access level:
- Super class>> Shape (in.bench.resources.method.overriding)
- Overridden method>> draw()
- access modifier: protected
- return type: void
- throws: Exception (java.lang.Exception)
- Sub class>> Circle (in.bench.resources.method.overriding)
- Extending Super class>> Shape (in.bench.resources.method.overriding)
- Overriding method>> draw()
- access modifier: public
- return type: void
- throws: Exception (java.lang.Exception)
In above example, access level in the draw() method of super class is ‘protected’. While overriding, access level has been broadened to ‘public’
So, access level in overriding concepts cannot be more restrictive rather it should be more broader/wider
5. Return type:
While overriding, return type should be exactly same or its sub classes (sub type)
5.1 Example for narrowing return type,
We will create dummy POJOs to illustrate this example within ‘in.bench.resources.pojo’ package
POJO 1: SuperClassA
POJO 2: SubClassB extending SuperClassA
- Super class>> Shape (in.bench.resources.method.overriding)
- Overridden method>> draw()
- access modifier: default (no explicit access modifier)
- return type: SuperClassA (in.bench.resources.pojo)
- throws: Exception (java.lang.Exception)
- Sub class>> Circle (in.bench.resources.method.overriding)
- Extending Super class>> Shape (in.bench.resources.method.overriding)
- Overriding method>> draw()
- access modifier: protected
- return type: SubClassB (in.bench.resources.pojo)
- throws: Exception (java.lang.Exception)
In above example, return type in the draw() method of super class is ‘SuperClassA’ and while overriding return type has been changed to ‘SubClassB’ which is a inheriting class from SuperClassA
So, return type in the overriding method can be same or its sub classes (or sub type from that of super class)
This is called co-variant return type in Java (Since JDK 1.5)
6. Exception Handling:
While overriding,
- throws clause should throw exactly same exception or its sub class’s exception (for checked exception)
- sub class compiles even if we don’t add throws clause in the overriding method in sub class –> when super class throws checked exception
- sub class can throw any number of un-checked exception (eg; RuntimeException) –> class compiles without any error/warning
6.1 Example for narrowing exception
- Super class>> Shape (in.bench.resources.method.overriding)
- Overridden method>> draw()
- access modifier: default
- return type: SuperClassA (in.bench.resources.pojo)
- throws: Exception (java.lang.Exception)
- Sub class>> Circle (in.bench.resources.method.overriding)
- Extending Super class>> Shape (in.bench.resources.method.overriding)
- Overriding method>> draw()
- access modifier: protected
- return type: SubClassB (in.bench.resources.pojo)
- throws: ClassNotFoundException (java.lang.ClassNotFoundException)
In above example, super class’s overridden draw() method throws ‘java.lang.Exception’ whereas overriding method throws ‘java.lang.ClassNotFound.Exception’ (which is sub-class of java.lang.Exception)
In addition to points discussed above for overriding a method in Java, there are few rules to abide while overriding method in sub class
7. Rules for Java method overriding:
- To override a method, first class has be to be inherited (or to be sub classed)
- Overriding method name and signature in the sub class should be exactly same as that of super class’s method
- Number of formal parameters and their order should be exactly same as that of the overridden method
- Access level cannot be more restrictive, rather it should be more wider/broader (widening concept)
- Return type should be same or its sub-type (narrowing concept). This is knowns as co-variant return type (applicable since Java 1.5)
- Exception in the throws clause should be same or its sub-type (narrowing concept)
- It is okay, not to throw any checked exception in the overriding method even when super class’s overridden method throws any checked exception but vice-versa results in compilation error
- Any number of un-checked exception can be thrown from overriding method regardless of whether overridden method throws any checked or un-checked exception in super class
- If super class method declared as final then it cannot be overridden
- If super class method declared as private then it cannot be overridden (Singleton design pattern)
- If super class method declared as static then it cannot be overridden rather it can be re-declared in inheriting class
- Constructor cannot be overridden
Related Articles:
- Java Method Overloading
- Interview Question and Answers on Method Overloading
- Interview Question and Answers on Method Overriding
- Difference between Method Overriding and Method Overloading in Java
References:
- https://docs.oracle.com/javase/tutorial/java/IandI/override.html
- https://javahungry.blogspot.com/2018/11/method-overriding-in-java-with-examples.html
Happy Coding !!
Happy Learning !!