Java Notes
Complete guide to Java inheritance — single, multilevel, and hierarchical inheritance, method inheritance, the IS-A relationship, composition vs inheritance, and the Diamond Problem.
Inheritance is a mechanism where a new class (child/subclass) acquires the properties and behaviors of an existing class (parent/superclass). It establishes an IS-A relationship — a Dog IS-A Animal, a Car IS-A Vehicle.
Inheritance promotes code reuse and enables polymorphism — the two most powerful benefits of OOP.
The extends Keyword
public class Animal {
protected String name;
protected int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name + " is eating");
}
public void sleep() {
System.out.println(name + " is sleeping");
}
public void displayInfo() {
System.out.println(name + ", " + age + " years old");
}
}
public class Dog extends Animal {
private String breed;
public Dog(String name, int age, String breed) {
super(name, age); // Initialize Animal part
this.breed = breed;
}
// New method specific to Dog
public void bark() {
System.out.println(name + " says: Woof! Woof!");
}
public void fetch(String item) {
System.out.println(name + " fetches the " + item);
}
@Override
public void displayInfo() {
super.displayInfo();
System.out.println("Breed: " + breed);
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Buddy", 3, "Golden Retriever");
// Inherited methods from Animal
dog.eat();
dog.sleep();
dog.displayInfo();
// Dog's own methods
dog.bark();
dog.fetch("ball");
}
}Buddy is eating Buddy is sleeping Buddy, 3 years old Breed: Golden Retriever Buddy says: Woof! Woof! Buddy fetches the ball
What Gets Inherited?
| Member | Inherited? | Notes |
|---|---|---|
public methods | ✅ Yes | Fully accessible |
protected methods | ✅ Yes | Accessible in subclass |
| Package-private (default) | ✅ If same package | Not accessible from different package |
private methods | ❌ No | Not visible to subclass |
public fields | ✅ Yes | Accessible (but avoid public fields) |
protected fields | ✅ Yes | Accessible in subclass |
private fields | ❌ No | Exist in object but not accessible directly |
| Constructors | ❌ No | Must define own, call parent via super() |
static methods | ✅ Yes | But not polymorphic (hiding, not overriding) |
Types of Inheritance
1. Single Inheritance
One child extends one parent:
public class Vehicle {
protected String brand;
protected int speed;
public void start() {
System.out.println(brand + " started");
}
public void accelerate(int amount) {
speed += amount;
System.out.println(brand + " accelerating: " + speed + " km/h");
}
}
public class Car extends Vehicle {
private int passengers;
public Car(String brand, int passengers) {
this.brand = brand;
this.passengers = passengers;
}
public void honk() {
System.out.println(brand + ": Beep beep!");
}
}2. Multilevel Inheritance
A chain of inheritance: A → B → C
public class LivingBeing {
public void breathe() {
System.out.println("Breathing...");
}
}
public class Animal extends LivingBeing {
public void move() {
System.out.println("Moving...");
}
}
public class Dog extends Animal {
public void bark() {
System.out.println("Barking...");
}
}
// Dog inherits from Animal AND LivingBeing
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.breathe(); // From LivingBeing
dog.move(); // From Animal
dog.bark(); // Own method
}
}Breathing... Moving... Barking...
3. Hierarchical Inheritance
Multiple children extend the same parent:
public class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
public double area() { return 0; }
}
public class Circle extends Shape {
private double radius;
public Circle(double radius, String color) {
super(color);
this.radius = radius;
}
@Override
public double area() { return Math.PI * radius * radius; }
}
public class Rectangle extends Shape {
private double width, height;
public Rectangle(double width, double height, String color) {
super(color);
this.width = width;
this.height = height;
}
@Override
public double area() { return width * height; }
}
public class Triangle extends Shape {
private double base, height;
public Triangle(double base, double height, String color) {
super(color);
this.base = base;
this.height = height;
}
@Override
public double area() { return 0.5 * base * height; }
}Why No Multiple Inheritance in Java?
Java does NOT support multiple class inheritance (extending two classes):
// ❌ NOT VALID IN JAVA
public class Amphibian extends LandAnimal, WaterAnimal { }The Diamond Problem: If both parents have the same method, which one does the child inherit?
Solution: Java uses interfaces for multiple inheritance of behavior:
public interface Swimmable {
void swim();
}
public interface Runnable {
void run();
}
public class Amphibian extends Animal implements Swimmable, Runnable {
@Override
public void swim() { System.out.println("Swimming"); }
@Override
public void run() { System.out.println("Running on land"); }
}IS-A Relationship and Type Checking
Inheritance establishes IS-A: every Dog IS-A Animal
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Rex", 5, "German Shepherd");
// IS-A checks
System.out.println(dog instanceof Dog); // true
System.out.println(dog instanceof Animal); // true - Dog IS-A Animal
System.out.println(dog instanceof Object); // true - everything IS-A Object
// Upcasting (implicit) - always safe
Animal animal = dog; // Dog reference stored in Animal variable
animal.eat(); // Works - eat() is in Animal
// animal.bark(); // ❌ Compile error - Animal doesn't know about bark()
// Downcasting (explicit) - must be checked
if (animal instanceof Dog) {
Dog d = (Dog) animal; // Safe downcast
d.bark(); // Now we can access Dog methods
}
}
}true true true Buddy is eating Buddy says: Woof! Woof!
Real-World Example: Employee Hierarchy
[DEV-001] Alice (Developer (Java/Spring)) - $90150.00 [MGR-001] Bob (Manager (team of 8)) - $126600.00 Total payroll: $216750.00
Composition vs Inheritance
Inheritance: IS-A relationship (Dog IS-A Animal) Composition: HAS-A relationship (Car HAS-A Engine)
// ❌ Bad: Using inheritance for HAS-A relationship
public class Car extends Engine { // A car IS NOT an engine!
}
// ✅ Good: Using composition
public class Car {
private Engine engine; // A car HAS an engine
private Transmission transmission;
private List<Wheel> wheels;
public Car(Engine engine, Transmission transmission) {
this.engine = engine;
this.transmission = transmission;
this.wheels = new ArrayList<>();
}
public void start() {
engine.ignite();
transmission.engage();
}
}When to Use Each
| Use Inheritance When | Use Composition When |
|---|---|
| Clear IS-A relationship | HAS-A relationship |
| Child IS a specialized parent | Object USES another object |
| Need polymorphism | Need flexibility to swap parts |
| Behavior is intrinsic | Behavior is delegated |
| Example: Dog extends Animal | Example: Car has Engine |
Rule of thumb: Prefer composition over inheritance. Use inheritance only for genuine IS-A relationships.
The Object Class — Root of Everything
Every class in Java implicitly extends Object:
public class MyClass { }
// Is equivalent to:
public class MyClass extends Object { }Methods inherited from Object:
toString()— String representationequals(Object)— Content equalityhashCode()— Hash code for collectionsgetClass()— Runtime class infoclone()— Object copyingfinalize()— Pre-GC cleanup (deprecated)wait(),notify(),notifyAll()— Thread coordination
Common Mistakes
- Inheriting for code reuse without IS-A:
``java // ❌ Stack IS NOT an ArrayList, it HAS one class Stack extends ArrayList { } // ✅ Use composition class Stack { private ArrayList list = new ArrayList(); } ``
- Deep inheritance hierarchies:
``java // ❌ Too many levels — fragile and hard to understand class A extends B extends C extends D extends E { } // ✅ Keep hierarchies shallow (2-3 levels max) ``
- Forgetting to call
super()with arguments:
``java class Child extends Parent { Child() { } // ❌ If Parent has no no-arg constructor, this fails } ``
- Breaking substitutability:
``java // Bird has fly(). Penguin extends Bird. // ❌ Penguin can't fly! Liskov Substitution violated. // ✅ Restructure: Separate FlyingBird from Bird ``
Best Practices
- Use inheritance for genuine IS-A relationships only
- Keep hierarchies shallow (prefer 2-3 levels)
- Prefer composition over inheritance for flexibility
- Design for extension: document what subclasses can override
- Use
finalon methods/classes that shouldn't be extended - Follow Liskov Substitution Principle — children must be valid parents
Interview Questions
Q1: Why doesn't Java support multiple inheritance? To avoid the Diamond Problem — ambiguity when two parents have the same method. Java uses interfaces instead, which allow multiple inheritance of type and behavior (with default methods).
Q2: What is the difference between IS-A and HAS-A? IS-A = inheritance (Dog IS-A Animal). HAS-A = composition (Car HAS-A Engine). Prefer HAS-A for flexibility.
Q3: Can a class extend itself? No. That would create a circular inheritance dependency.
Q4: What is the superclass of all classes? java.lang.Object. Every class implicitly extends Object if no other parent is specified.
Q5: Can you inherit constructors? No. Constructors are not inherited. Each class must define its own and call the parent's via super().
Q6: What is the difference between aggregation and composition? Both are HAS-A. Composition = strong ownership (Engine dies with Car). Aggregation = weak reference (Department has Employees, but employees exist independently).
Q7: Can a final class be inherited? No. final prevents subclassing. String, Integer, and Math are final classes.
Q8: Why doesn't Java support multiple inheritance with classes? Multiple class inheritance creates the "diamond problem" — if class C extends both A and B, and both have a method show(), which version does C inherit? This ambiguity leads to complex rules. Java avoids it by allowing multiple inheritance only through interfaces (where default method conflicts must be explicitly resolved).
Q9: What is the difference between extends and implements? extends is used for class inheritance (single parent only) and interface inheritance. implements is used when a class implements one or more interfaces. A class can extends one class AND implements multiple interfaces simultaneously.
Q10: What is constructor behavior in inheritance? Child class constructors must call a parent constructor (via super()). If not explicit, compiler adds super() automatically. Parent constructor ALWAYS executes before child constructor. This ensures the parent's portion is fully initialized before child adds its own state.
Q11: Can a child class access grandparent's members directly? Yes, if they're public or protected. Inherited members pass through all levels. A field declared protected in class A is accessible in class C (which extends B, which extends A). You cannot skip levels with super.super though.
Q12: What is the Liskov Substitution Principle in inheritance? LSP states that objects of a child class should be usable wherever the parent class is expected, without breaking behavior. If Bird has fly(), then Penguin extends Bird violates LSP because penguins can't fly. This means inheritance should model true "is-a" relationships.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Inheritance in Java.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, oops, inheritance, inheritance in java
Related Java Master Course Topics