Inheritance is the pillar of OOP that interviewers reach for first, because a wrong answer here exposes shaky fundamentals immediately. It is also the feature beginners misuse most often — extending classes just to reuse a method, then wondering why their design falls apart two weeks later.
This tutorial walks through inheritance the way we teach it in class: real code, the super keyword, overriding, and the honest answer to "should I even use inheritance here?" If you have not yet read the overview of all four OOP pillars, skim that first — this page goes deep on one pillar.
What inheritance actually means
Inheritance lets one class acquire the fields and methods of another. The class being extended is the superclass (parent), and the class doing the extending is the subclass (child). The keyword is extends.
The mental test is the is-a relationship. A Manager is an Employee. A SavingsAccount is a BankAccount. If you cannot say "X is a Y" out loud without it sounding wrong, inheritance is the wrong tool.
Two things a subclass gets to do:
- Reuse — every non-private field and method of the parent works on the child without rewriting it.
- Specialize — the child adds new members or overrides inherited methods to change behavior.
A real example: Employee and Manager
Here is a complete, runnable example. Notice that Manager never declares name, salary, or displayDetails(), yet uses all three.
class Employee {
String name;
double salary;
Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
void displayDetails() {
System.out.println(name + " earns " + salary);
}
}
class Manager extends Employee {
int teamSize;
Manager(String name, double salary, int teamSize) {
super(name, salary); // must run the parent constructor first
this.teamSize = teamSize;
}
void conductReview() {
System.out.println(name + " is reviewing " + teamSize + " people");
}
}
public class Main {
public static void main(String[] args) {
Manager m = new Manager("Anitha", 95000, 6);
m.displayDetails(); // inherited from Employee
m.conductReview(); // Manager's own method
}
}
What to notice: Manager has access to name directly because the field has default (package) access. If Employee declared it private, Manager would need a getter — private members are present in the child object's memory but not accessible by name.
Common mistake: A common mistake beginners make is thinking
privatemembers are "not inherited at all." They exist inside every child object — the child just cannot touch them directly. That is exactly why encapsulation pairs private fields with public getters.
The super keyword and constructor chaining
super does three jobs:
| Usage | Meaning |
|---|---|
super(args) |
Call a parent constructor (must be the first statement) |
super.method() |
Call the parent's version of an overridden method |
super.field |
Access a parent field hidden by a child field of the same name |
Constructors are not inherited, but they chain. When you write new Manager(...), Java runs Object's constructor, then Employee's, then Manager's — top of the hierarchy downward. If you do not write super(...) yourself, the compiler inserts a call to the parent's no-argument constructor. If the parent has no no-arg constructor, your code will not compile until you call super(...) explicitly.
class Vehicle {
Vehicle() {
System.out.println("Vehicle constructor");
}
}
class Car extends Vehicle {
Car() {
// compiler inserts super(); here
System.out.println("Car constructor");
}
}
public class ChainDemo {
public static void main(String[] args) {
new Car();
// Output:
// Vehicle constructor
// Car constructor
}
}
What to notice: the parent line prints first even though you only constructed a Car. Interviewers love asking you to predict this output.
Method overriding: changing inherited behavior
Overriding means the subclass provides its own body for a method it inherited, keeping the same signature. This is where inheritance connects to runtime polymorphism — the JVM picks the child's version even when the reference type is the parent.
class BankAccount {
protected double balance = 10000;
double withdrawalLimit() {
return 25000;
}
}
class SavingsAccount extends BankAccount {
@Override
double withdrawalLimit() {
return 10000; // savings accounts have a tighter limit
}
}
public class OverrideDemo {
public static void main(String[] args) {
BankAccount acc = new SavingsAccount(); // parent reference, child object
System.out.println(acc.withdrawalLimit()); // prints 10000.0
}
}
What to notice: the reference type is BankAccount, yet the output is 10000.0 — the JVM dispatched to SavingsAccount's method at runtime.
Pro tip: Always write
@Overrideabove an overriding method. It costs nothing and turns a silent bug (typo in the method name creates a new method instead of overriding) into a compile error.
Rules to remember when overriding:
- Same method name and parameter list; return type must be the same or a subtype (covariant return).
- Access level cannot be more restrictive — you can widen
protectedtopublic, never narrow it. - You cannot override
final,static, orprivatemethods. Redefining astaticmethod is called method hiding, and it resolves by reference type, not object type.
Types of inheritance Java supports
| Type | Shape | Supported with classes? |
|---|---|---|
| Single | A → B | Yes |
| Multilevel | A → B → C | Yes |
| Hierarchical | A → B, A → C | Yes |
| Multiple | A, B → C | No (classes); yes via interfaces |
| Hybrid | Mix of the above | Only where interfaces carry the multiple part |
Java forbids multiple inheritance of classes because of the diamond problem: if C extends A, B and both parents define show(), which one does C inherit? Rather than invent tie-breaking rules for state, the language designers banned it. Interfaces sidestep the issue because they historically carried no state — and when Java 8 default methods reintroduced a mild diamond, the compiler simply forces you to override the conflicting method. See abstraction in Java for how interfaces fill this gap.
What gets inherited — and what doesn't
Inherited:
public,protected, and (same-package) default fields and methods- Nested types declared in the parent
Not inherited:
- Constructors (they chain, but each class declares its own)
privatemembers (present in memory, not accessible)staticmembers are shared through the class, not truly inherited per-object
Every class you write silently extends java.lang.Object, which is why toString(), equals(), and hashCode() exist on everything you create.
Inheritance vs composition: the design decision
The most senior-sounding thing a fresher can say in an interview is "I'd prefer composition here." Composition means holding another object as a field and delegating to it, instead of extending its class.
// Composition: a Car HAS-AN engine, it is not a kind of engine
class Engine {
void start() { System.out.println("Engine started"); }
}
class Car {
private final Engine engine = new Engine();
void start() {
engine.start(); // delegate
System.out.println("Car moving");
}
}
Choose inheritance when the is-a test passes and you want callers to substitute the child anywhere the parent is expected. Choose composition when you just want to reuse behavior — it keeps the two classes independently changeable and avoids a fragile hierarchy where one parent edit breaks five children.
Interview note: "Why does Java favor composition over inheritance?" is a standard follow-up at product companies in Hyderabad. Anchor your answer on coupling: inheritance couples the child to the parent's implementation details; composition couples it only to a public API. Practice more variants on our Java OOP interview questions page.
Where to go next
Inheritance is the mechanism; polymorphism is the payoff. Read Polymorphism in Java next to see why "parent reference, child object" is the single most useful line in this article. If you want the full picture with mentor-led practice — inheritance hierarchies, design exercises, and interview drills — that is exactly what week three of our Java Full Stack course covers.
Frequently Asked Questions
What is inheritance in Java in simple words?
Why does Java not support multiple inheritance of classes?
What is the difference between extends and implements?
Are constructors inherited in Java?
Can we override private or static methods in Java?
When should I use composition instead of inheritance?
Want to Build Your Career in Java Full Stack with AI?
Join CodeBegun and train with working industry engineers — Explore the Program

