All About Overriding in Java
If you want to ensure you're overriding the right way, take a look at this guide, which dives into the various means at your disposal and some pitfalls to watch out for.
Join the DZone community and get the full member experience.
Join For FreeA child class can redefine the instance methods of its parent class. This is called method overriding. The signature (return type, parameter type, the number of parameters, and order of parameters) must be the same as defined in the parent class. Method overriding is done to achieve runtime polymorphism.
What Is Polymorphism?
Polymorphism allows you define one interface and have multiple implementations. This is one of the basic principles of object-oriented programming. The word ‘polymorphism’ literally means ‘a state of having many shapes’ or ‘the capacity to take on different forms.’ When applied to object-oriented programming languages like Java, it describes a language’s ability to process objects of various types and classes through a single, uniform interface.
What Is Runtime Polymorphism (or Dynamic Method Dispatch?)
An overridden method is called according to the object invoking it, not according to the reference type.
What Is the Use of Runtime Polymorphism?
Static vs. Dynamic Polymorphism?
Private, final, and static methods and variables use static bindings and are bonded by compiler while virtual methods are bonded during runtime based on the runtime object.
@Override Usage
Use @Override so that you can take advantage of the compiler to make sure you actually are overriding a method when you think you are. This way, if you make a common mistake like misspelling a method name or not correctly matching the parameters, you will be warned that your method does not actually override like you think it does. Secondly, it makes your code easier to understand because it is more obvious when methods are overwritten.
Additionally, in Java 1.6, you can use it to mark when a method implements an interface for the same benefits.
Rules for Dynamic Polymorphism
Change in Method Signature
If we use overriding, then the overriding method should have the same signature as the overridden method. You can change the method signature accordingly in your child class, i.e number of arguments, type and order of arguments, and return type. But this is known as overloading.
package com.me.overriding;
class Parent_params {
void method(String a, String b, int v, float d) {
System.out.println("parent");
}
void method2(String a, String b, int v) {
System.out.println("parent");
}
void method3(String a, int v) {
System.out.println("parent");
}
}
class Child_Params extends Parent_params {
//If we want to override the parent class you need to have same
//no of params as parent had
//WRONG...
/*@Override
void method(String a){
System.out.println("child");
}*/
//Order of the params should also be same as parent
//WRONG
/*@Override
void method(String a,float d,int a,String b){
System.out.println("parent");
}*/
//Override
@Override
void method(String a, String b, int v, float d) {
System.out.println("child");
}
//Overloading
//We can define a method like this
void method(String a, String b, int v) {
System.out.println("child");
}
void method2(String a, int b, String v) {
System.out.println("child");
}
void method3(int v, String a) {
System.out.println("child");
}
}
public class Override_Params {
public static void main(String[] args) {
String temp = "Monday";
Child_Params child_Params = new Child_Params();
/*Parent_params params=new Child_Params();
child_Params=(Child_Params) params;
child_Params.method(temp,temp,2);*/
Parent_params params2 = new Parent_params();
child_Params = (Child_Params) params2;
child_Params.method(temp, temp, 2);
/*up vote
3
down vote
accepted
Once you create an object, you can't change its type.
That's why you can't cast an Animal to a Dog.
However, if you create an object of a sub-class,
you can keep a reference to it in a variable of the super-class type,
and later you can cast it to the sub-class type.
This will work :
Animal a = new Dog ();
Dog d = (Dog) a;*/
}
}
Return Type of the Method
Return types may vary among methods that override each other if the return types are reference types. The notion of return-type-substitutability supports covariant returns — the specialization of the return type to a subtype. A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2 if and only if the following conditions hold:
If R1 is void then R2 is void.
If R1 is a primitive type, then R2 is identical to R1.
If R1 is a reference type then: R1 is either a subtype of R2 or R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9), or
R1 = |R2|
package com.me.overriding;
class Parent1 {
public void method(String string) {
System.out.println("Parent :" + string);
}
public void method2(String string) {
System.out.println("Parent :" + string);
}
}
class Child1 extends Parent1 {
//The return type is incompatible with Parent1.method(String)
@Override
public int method(String string) {
System.out.println("Child :" + string);
}
}
public class OverrideAllMethods {
public static void main(String[] args) {
Child1 child1 = new Child1();
child1.method("Me");
}
}
Co-Variant Return Type
A covariant return means that when one overrides a method, the return type of the overriding method is allowed to be a subtype of the overridden method's return type.
To clarify this with an example, a common case is Object.clone(), which is declared to return a type of Object. You could override this in your own class as follows:
package com.me.overriding;
class ParentCustomClass {
public Object m1() {
System.out.println(" parent m1()");
return null;
}
public ParentCustomClass m2() {
System.out.println(" parent m2()");
return null;
}
}
class ChildtCustomClass extends ParentCustomClass {
@Override
public String m1() {
System.out.println("child m1()");
return null;
}
@Override
public ChildtCustomClass m2() {
System.out.println(" child m2()");
return null;
}
}
public class CoVarientTypes {
public static void main(String[] args) {
ParentCustomClass class1 = new ChildtCustomClass();
class1.m1();
class1.m2();
/*A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2, if and only if the following conditions hold:
If R1 is void then R2 is void.
If R1 is a primitive type, then R2 is identical to R1.
If R1 is a reference type then:
R1 is either a subtype of R2 or R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9), or
R1 = |R2|*/
}
}
Static Method Overriding (or) Method Binding
package com.me.overriding;
class ParentStatic {
public static void method(String string) {
System.out.println("Parent :" + string);
}
public void method2(String string) {
System.out.println("Parent :" + string);
}
}
class ChildStatic extends ParentStatic {
public static void method(String string) {
System.out.println("Child :" + string);
}
}
public class StaticMethodOverriding {
public static void main(String[] args) {
/*1) For class (or static) methods, the method according to the type of
reference is called, not according to the abject being referred, which means
method call is decided at compile time.
2) For instance (or non-static) methods, the method is called according to the type
of object being referred, not according to the type of reference, which means method
calls is decided at run time.*/
ChildStatic.method("Me");
ParentStatic parentStatic = new ChildStatic();
parentStatic.method("Me");
}
}
Static Variable Binding
package com.me.overriding;
class Dad {
private static final String me = "dad";
protected String getMe() {
return me;
}
public void printMe() {
System.out.println(getMe());
}
}
class Son extends Dad {
private static final String me = "son";
@Override
protected String getMe() {
return me;
}
}
class StaticVariableOverriding {
public static void main(String[] args) {
Dad dad = new Son();
dad.printMe();
}
}
Final and Private Methods
package com.me.overriding;
class Parent_2 {
public final void m1() {
System.out.println("m1()");
}
private void m2() {
System.out.println("m2() parent");
}
}
//Cannot override the final method from Parent_2
class Child_2 extends Parent_2 {
public fianl void m1() {
System.out.println("m1()");
}
private void m2() {
System.out.println("m2() of child");
}
}
public class FinalandprivateOverriden {
public static void main(String[] args) {
Parent_2 child_2 = new Child_2();
child_2.m1();
//The method m2() from the type Parent_2 is not visible
child_2.m2();
}
}
Override Access Levels
package com.me.overriding;
class Parent_Access {
protected void method(String a, String b, int v, float d) {
System.out.println("parent");
}
}
class Child_Access extends Parent_Access {
//Access levels cannot be restrictive
/*private void method(String a,String b,int v,float d){
System.out.println("parent");
}*/
public void method(String a, String b, int v, float d) {
System.out.println("parent");
}
}
public class Override_AccessLevels {
public static void main(String[] args) {
}
}
Override With super()
package com.me.overriding;
class SuperParent {
public void m1() {
System.out.println(" super m1()");
}
protected void m2() {
System.out.println(" super m2()");
}
private void m3() {
System.out.println(" super m3()");
}
}
class SuperChild extends SuperParent {
public void m1() {
super.m1();
super.m2();
System.out.println("m1()");
}
protected void m2() {
System.out.println("m2()");
}
private void m3() {
System.out.println(" m3()");
}
}
public class OverridingWithSuper {
public static void main(String[] args) {
SuperParent parent = new SuperChild();
parent.m1();
parent.m2();
}
}
Override With Abstraction
package com.me.overriding;
interface Interface {
public void m1();
}
/*If an abstract class implements the above interface,
then it doesn’t require the subclass to override the move() method,
as shown in the following AbstractDog class:*/
abstract class AbstractClass implements Interface {
public abstract void m2();
public void m3() {
System.out.println("m3()");
}
}
/*//But if a concrete (non-abstract) class, says BullDog, is a subclass of the
AbstractDog class or the Animal interface, then it must override all the inherited
abstract methods, as shown below:*/
class ConcreteClass extends AbstractClass {
@Override
public void m1() {
// TODO Auto-generated method stub
System.out.println("m1()");
}
@Override
public void m2() {
// TODO Auto-generated method stub
System.out.println("m2()");
}
@Override
public void m3() {
// TODO Auto-generated method stub
System.out.println("m3()");
}
}
public class OverridingWithAbstraction {
public static void main(String[] args) {
ConcreteClass class1 = new ConcreteClass();
class1.m1();
class1.m2();
class1.m3();
}
}
Override With Exceptions
package com.me.overriding;
import java.io.IOException;
import java.nio.file.DirectoryIteratorException;
class ExceptionParent {
public void m1() throws IOException {
System.out.println("m1()");
}
}
//Exception Exception is not compatible with throws clause in ExceptionParent.m1()
//It should be sam or narrowed or unchecked exception
//CE
/*class ExceptionChild extends ExceptionParent{
public void m1() throws Exception{
System.out.println("m1()");
}*/
//CE
//IllegalArgumentException is Un-checked
/*class ExceptionChild extends ExceptionParent{
public void m1() throws Exception,IllegalArgumentException{
System.out.println("m1()");
}*/
//OK bccz of Un-Checked Exception
/*class ExceptionChild extends ExceptionParent{
public void m1() throws IllegalArgumentException{
System.out.println("m1()");
}*/
/*//CE bcz of Checked
class ExceptionChild extends ExceptionParent{
public void m1() throws IOException,InterruptedException{
System.out.println("m1()");
}*/
class ExceptionChild extends ExceptionParent {
public void m1() throws IOException {
System.out.println("m1()");
}
}
public class OverridingExceptions {
public static void main(String[] args) throws IOException {
ExceptionParent exceptionParent = new ExceptionChild();
exceptionParent.m1();
}
}
Overriding From Inner Private Classes
package com.me.overriding;
/* Java program to demonstrate whether we can override private method
of outer class inside its inner class */
public class OverrideprivateInnerclass {
private String msg = "GeeksforGeeks";
private void fun() {
System.out.println("Outer fun()");
}
class Inner extends OverrideprivateInnerclass {
private void fun() {
System.out.println("Accessing Private Member of Outer: " + msg);
}
}
public static void main(String args[]) {
// In order to create instance of Inner class, we need an Outer
// class instance. So, first create Outer class instance and then
// inner class instance.
OverrideprivateInnerclass o = new OverrideprivateInnerclass();
Inner i = o.new Inner();
// This will call Inner's fun, the purpose of this call is to
// show that private members of Outer can be accessed in Inner.
i.fun();
// o.fun() calls Outer's fun (No run-time polymorphism).
o = i;
o.fun();
}
}
Overriding and Overloading
package com.me.overriding;
class ParentStatic_1 {
public void method(String string) {
System.out.println("Parent :" + string);
}
public void method2(String string) {
System.out.println("Parent :" + string);
}
}
class ChildStatic_1 extends ParentStatic_1 {
public static void method(String string, int b) {
System.out.println("Child :" + string);
}
public static void method2(String string, int b, float c) {
System.out.println("Child :" + string);
}
}
public class OverrideAndOverloadMethods {
public static void main(String[] args) {
//In a subclass (or Derived Class), we can overload the methods inherited from the
//superclass. Such overloaded methods neither hide nor override the superclass methods — they are new methods, unique to the subclass.
ParentStatic_1 parentStatic = new ChildStatic_1();
parentStatic.method("Me");
}
}
Multi-Level Override
package com.me.overriding;
class ParentStatic_2 {
public void method(String string) {
System.out.println("Parent :" + string);
}
public void method2(String string) {
System.out.println("Parent :" + string);
}
}
class ChildStatic_2 extends ParentStatic_2 {
public void method(String string) {
System.out.println("Child -1 :" + string);
}
}
class ChildStatic_3 extends ChildStatic_2 {
public void method(String string) {
System.out.println("Child -2 :" + string);
}
}
class ChildStatic_4 extends ChildStatic_3 {
public void method(String string) {
System.out.println("Child -3 :" + string);
}
}
public class MultilevelOverriding {
public static void main(String[] args) {
//We no need to overwrite all the methods that are there in super class.
ParentStatic_2 parentStatic_2 = new ChildStatic_3();
parentStatic_2.method("hey........!");
}
}
Instance vs Static Method Override
package com.me.overriding;
class ParentStatic2 {
public static void method(String string) {
System.out.println("Parent :" + string);
}
public void method2(String string) {
System.out.println("Parent :" + string);
}
}
class ChildStatic2 extends ParentStatic {
//This static method cannot hide the instance method from ParentStatic
public void method(String string) {
System.out.println("Child :" + string);
}
//This static method cannot hide the instance method from ParentStatic
public static void method2(String string) {
System.out.println("Child :" + string);
}
}
public class InstanceVsStaticOverriding {
public static void main(String[] args) {
//An instance method cannot override a static method,
//and a static method cannot hide an instance method.
ParentStatic2 parentStatic = new ChildStatic2();
parentStatic.method("Me");
}
}
Instance vs. Static Variable Override
package com.me.overriding;
class B
{
int a=10;
public void print()
{
System.out.println("inside B super class");
}
}
class C extends B
{
int a=20;
public void print()
{
System.out.println("inside C sub class");
}
}
public class InstanceVariableOverriding {
public static void main(String[] args) {
B b=new C();
b.print();//it will print inside c sub class
System.out.println(b.a);//it will print super class variable value=10
/*
Why instance variable of super class is not overridden in sub class method see my code below ...
Because instance variables CANNOT be overridden in Java. In Java only methods can be overridden.
When you declare a field with the same name as an existing field in a
superclass, the new field hides the existing field. The existing field from
the superclass is still present in the subclass, and can even be used ...
subject to the normal Java access rules.*/
}
}
Constructor Override
package com.me.overriding;
class One {
public One() { // Super Class constructor
}
One(int a) { // Super Class Constructor Overloading
}
}
class Two extends One {
/* {
//One() { // this is a method not constructor
// because name should not match with Class name
}*/
Two() { // sub class constructor
}
Two(int b) { // sub class constructor overloading
}
}
public class ConstructorOverriding {
/*It is never possible. Constructor Overriding is never possible in Java.
This is because,
Constructor looks like a method but name should be as class name and no return value.
Overriding means what we have declared in Super class, that exactly we have to declare in Sub class it is called Overriding. Super class name and Sub class names are different.
If you try to write Super class Constructor in Sub class, then Sub class will treat that a*/
//s a method not constructor because name should not match with Sub class name. And it will give an compilation error that methods does not have return value. So we should declare as void, then only it will compile.
}
Constructor With super()
package com.me.overriding;
class Superclass {
public Superclass(int x) {
System.out.println("000000");
}
public Superclass() {
System.out.println(" ty");
}
public Superclass(String y) {}
}
class Subclass extends Superclass {
public Subclass() {
// super(5); // chain to Superclass(int) constructor
}
}
public class ConstructorWithSuper {
public static void main(String[] args) {
new Subclass();
}
}
Other Package and Same Package Override
package com.me.overridingtest;
import com.me.overriding.PackageParent;
public class Child extends PackageParent {
@Override
public void m1() {
System.out.println("m1()");
}
@Override
protected void m2() {
System.out.println("m2()");
}
//Defalut methods are allowed only ininterface
/*default void m3(){
System.out.println("m3()");
}*/
//A subclass in a different package can only override the non-final
//methods declared public or protected.
@Override
private void m4() {
System.out.println("m1()");
}
}
package com.me.overriding;
import com.me.overridingtest.Parent;
public class OtherPackageOverride {
public static void main(String[] args) {
Parent parent = new com.me.overridingtest.Child();
parent.m1();
parent.m2();
}
}
package com.me.overriding;
public class PackageParent {
public void m1() {
System.out.println("m1()");
}
protected void m2() {
System.out.println("m2()");
}
//Defalut methods are allowed only ininterface
/*default void m3(){
System.out.println("m3()");
}*/
private void m4() {
System.out.println("m1()");
}
}
|
Class | Package | Subclass | Subclass | World |
| | (same pkg) | (diff pkg) | ————————————+——————— +————————— +—————————— +—————————— +————————
public | + | + | + | + | +———————————— +——————— +————————— +—————————— +—————————— +————————
protected | + | + | + | + | o———————————— + ——————— +————————— +—————————— +—————————— +————————
no modifier | + | + | + | o | o———————————— + ——————— +————————— +—————————— +—————————— +————————
private | + | o | o | o | o
+
: accessible
o: not accessible
Child-Parent Rules: Consequences With Overriding
//Child Parents Rules While IS-A relationship:
package com.me.overriding;
class Parent {
public void method(String string) {
System.out.println("Parent :" + string);
}
public void method2(String string) {
System.out.println("Parent :" + string);
}
}
class Child extends Parent {
@Override
public void method(String string) {
System.out.println("Child :" + string);
}
}
public class ChildParenRule {
public static void main(String[] args) {
//All well it will print
// Parent :Me
//Parent parent=new Parent();
//parent.method("Me");
//If we comment method in Parent and remove override in child
//It throws CE
//if we cast it to child also will get RE
//Exception in thread "main" java.lang.ClassCastException: com.me.overriding.Parent cannot be cast to com.me.overriding.Child
//at com.me.overriding.ChildParenRule.main(ChildParenRule.java:19)
//Parent parent2=new Parent();
//((Child) parent).method("Me");
//Calls the child lass Method,If not found calls
//Parent class's Method
//Child child=new Child();
//child.method("Me");
//Though Reference type is Parent overriding occurs at RE
//It will take as child object and calls child method
//if not there it will search for parent class method
//Parent parent=new Child();
//parent.method("Me");
//CE as Type mismatch: cannot convert from Parent to Child
//We can't convert parent to child class
//Exception in thread "main" java.lang.Error: Unresolved compilation problems:
//Syntax error, insert "VariableDeclarators" to complete LocalVariableDeclaration
//Syntax error, insert ";" to complete LocalVariableDeclarationStatement
//at com.me.overriding.ChildParenRule.main(ChildParenRule.java:53)
//Child child=(Child) new Parent();
//child.method("Me");
//
/*6
down vote
A parent class should not have knowledge of child classes.
Parent parent=new Parent();
((Child)parent).method("Me");*/
}
}
Instance Methods Are Preferred Over Interface Default Methods
package com.me.overriding;
//Instance methods are preferred over interface default methods.
//Consider the following classes and interfaces:
class Horse1 {
public String identifyMyself() {
return "I am a horse.";
}
}
interface Flyer {
default public String identifyMyself() {
return "I am able to fly.";
}
}
interface Mythical {
default public String identifyMyself() {
return "I am a mythical creature.";
}
}
public class Pegasus extends Horse1 implements Flyer, Mythical {
public static void main(String...args) {
Pegasus myApp = new Pegasus();
System.out.println(myApp.identifyMyself());
}
}
//The method Pegasus.identifyMyself returns the string I am a horse.
The programs having comments to illustrate the usage and consequances while overrding, It might have Some CE and RE.Plese Let me know if you came across any mistake(s) in below programs.
Published at DZone with permission of Madhusudana Singana. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments