Method Overriding (Run-Time)
Part of the Object Oriented Programming section of Coddy's Java journey — lesson 29 of 87.
While method overloading is resolved at compile time, method overriding demonstrates run-time polymorphism. Here, Java decides which method to execute when the program is actually running, based on the object's actual type rather than the variable's declared type.
You learned about method overriding in the Inheritance chapter. What makes it polymorphic is how Java handles it when a parent reference points to a child object:
public class Animal {
public void speak() {
System.out.println("Some sound");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("Bark!");
}
}
public class Cat extends Animal {
@Override
public void speak() {
System.out.println("Meow!");
}
}Now observe what happens when we use parent-type references:
Animal myPet = new Dog();
myPet.speak(); // Output: Bark!
myPet = new Cat();
myPet.speak(); // Output: Meow!Even though myPet is declared as Animal, Java calls the overridden method based on the actual object type at runtime. This is called dynamic method dispatch. The JVM looks at what the object really is, not what the variable says it is.
This enables powerful patterns like processing different objects uniformly:
Animal[] pets = {new Dog(), new Cat(), new Dog()};
for (Animal pet : pets) {
pet.speak(); // Each calls its own version
}Run-time polymorphism lets you write flexible code that works with parent types while automatically using the correct child behavior.
Challenge
EasyLet's build a notification system that demonstrates run-time polymorphism in action. You'll create a hierarchy of notification types where the same method call produces different outputs depending on the actual object type at runtime.
You'll organize your code across four files:
Notification.java: Create the base class that all notifications share. Every notification has arecipientfield (String). Include a constructor to initialize it, a getter method, and asend()method that prints:Sending notification to [recipient]EmailNotification.java: Create a class that extends Notification. Email notifications add asubjectfield. Usesuperfor the parent initialization. Override thesend()method to print:Emailing [recipient]: [subject]SMSNotification.java: Create another class that extends Notification. SMS notifications add aphoneNumberfield. Overridesend()to print:Texting [phoneNumber] for [recipient]Main.java: Here's where run-time polymorphism shines! You'll receive three inputs: a recipient name, an email subject, and a phone number. Create an array ofNotificationreferences containing three objects in this order: a base Notification, an EmailNotification, and an SMSNotification (all using the same recipient). Then loop through the array and callsend()on each element. Watch how Java automatically calls the correct overridden version based on what each object actually is!
You will receive three inputs: the recipient name (String), the email subject (String), and the phone number (String).
Your output should show three lines - each send() call produces different output even though you're calling the same method on Notification references. That's dynamic method dispatch at work!
Cheat sheet
Method overriding demonstrates run-time polymorphism, where Java decides which method to execute when the program is running, based on the object's actual type rather than the variable's declared type.
When a parent reference points to a child object, Java calls the overridden method based on the actual object type at runtime:
public class Animal {
public void speak() {
System.out.println("Some sound");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("Bark!");
}
}
Animal myPet = new Dog();
myPet.speak(); // Output: Bark!
myPet = new Cat();
myPet.speak(); // Output: Meow!This is called dynamic method dispatch. The JVM looks at what the object really is, not what the variable says it is.
Run-time polymorphism enables processing different objects uniformly:
Animal[] pets = {new Dog(), new Cat(), new Dog()};
for (Animal pet : pets) {
pet.speak(); // Each calls its own version
}Try it yourself
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Read inputs
String recipient = scanner.nextLine();
String subject = scanner.nextLine();
String phoneNumber = scanner.nextLine();
// TODO: Create an array of Notification references with 3 elements
// The array should contain (in this order):
// 1. A base Notification object
// 2. An EmailNotification object
// 3. An SMSNotification object
// All using the same recipient
// TODO: Loop through the array and call send() on each element
// This demonstrates run-time polymorphism!
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System