Java Programming · Lesson 8 of 15 · Updated ·
Inheritance and Polymorphism in Java — extends, super, Overriding
Inheritance lets a class reuse another class's fields and methods. Polymorphism lets one piece of code work with many related types. Together they are the heart of Java OOP.
1. extends and super
class Employee {
String name;
double salary;
Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
String work() { return name + " is working"; }
}
class Manager extends Employee {
int teamSize;
Manager(String name, double salary, int teamSize) {
super(name, salary); // must be the first line
this.teamSize = teamSize;
}
@Override
String work() { return super.work() + " and managing " + teamSize + " people"; }
}
public class Main {
public static void main(String[] args) {
System.out.println(new Employee("Ravi", 40000).work());
System.out.println(new Manager("Neha", 90000, 5).work());
}
}
Ravi is working
Neha is working and managing 5 people
class Manager extends Employee— Manager is an Employee.super(...)calls the parent constructor;super.work()calls the parent's method.@Overrideasks the compiler to check that you really are overriding.
Java supports single inheritance of classes (one parent), but a class can implement many interfaces (next lesson).
2. Runtime polymorphism
A parent-type variable can hold a child object. When you call an overridden method, Java runs the child's version — decided at runtime.
class Shape {
double area() { return 0; }
}
class Circle extends Shape {
double r;
Circle(double r) { this.r = r; }
@Override double area() { return Math.PI * r * r; }
}
class Rectangle extends Shape {
double w, h;
Rectangle(double w, double h) { this.w = w; this.h = h; }
@Override double area() { return w * h; }
}
public class Main {
public static void main(String[] args) {
Shape[] shapes = { new Circle(1), new Rectangle(3, 4), new Circle(2) };
double total = 0;
for (Shape s : shapes) {
total += s.area(); // the right area() runs for each object
}
System.out.printf("%.2f%n", total);
}
}
27.71
The loop doesn't know or care which shape it has. Add a Triangle class later and this loop works without changes. That's the power of polymorphism.
3. Overloading vs overriding (most asked)
| Overloading | Overriding | |
|---|---|---|
| Where | same class | parent and child class |
| Method name | same | same |
| Parameters | different | same |
| Decided at | compile time (static) | runtime (dynamic) |
| Also called | compile-time polymorphism | runtime polymorphism |
4. Upcasting, downcasting and instanceof
class Animal { String sound() { return "..."; } }
class Dog extends Animal {
@Override String sound() { return "Woof"; }
String fetch() { return "fetching"; }
}
public class Main {
public static void main(String[] args) {
Animal a = new Dog(); // upcasting: automatic
System.out.println(a.sound()); // Dog's version
if (a instanceof Dog d) { // check, then downcast (Java 16+ pattern)
System.out.println(d.fetch());
}
}
}
Woof
fetching
Through an Animal variable you can only call methods that Animal declares; to call fetch() you must downcast — after checking with instanceof.
5. The final keyword
finalvariable → can't be reassigned (a constant).finalmethod → can't be overridden.finalclass → can't be extended (Stringis final).
Common mistakes
- Forgetting
super(...)when the parent has no no-argument constructor (compile error). - Thinking a parent variable can call child-only methods without a cast.
- Changing parameters while trying to override (that's overloading — use
@Overrideto catch it).
Quick recap
extends= is-a;superreaches the parent.- Overriding + parent-type variables = runtime polymorphism.
- Overloading (compile time) vs overriding (runtime).
instanceofbefore downcasting;finalstops changes.