Inheritance
Inheritance lets one class acquire the fields and methods of another, so you can build on existing code instead of rewriting it from scratch. It is one of the four pillars of object-oriented programming and the feature that makes deep, expressive class hierarchies possible in Java.
What Is Inheritance?
When class B inherits from class A, B automatically gets every non-private field and method defined in A. You describe this relationship with the extends keyword.
Ais called the superclass (also: parent class, base class).Bis called the subclass (also: child class, derived class).
The relationship is often described as IS-A: a Dog IS-A Animal, a SavingsAccount IS-A BankAccount.
// Superclass
class Animal {
String name;
void eat() {
System.out.println(name + " is eating.");
}
}
// Subclass — inherits eat() from Animal
class Dog extends Animal {
void bark() {
System.out.println(name + " says: Woof!");
}
}
public class Main {
public static void main(String[] args) {
Dog d = new Dog();
d.name = "Rex"; // field inherited from Animal
d.eat(); // method inherited from Animal
d.bark(); // Dog's own method
}
}
Output:
Rex is eating.
Rex says: Woof!
Note: Java supports single inheritance for classes — a class can extend exactly one superclass. Multiple inheritance of classes is not allowed (it causes the “Diamond Problem”). You can, however, implement multiple interfaces.
The extends Keyword
extends is the only keyword you need to establish inheritance in Java:
class Subclass extends Superclass { }
If you don’t write extends, your class implicitly extends java.lang.Object — the root of every Java class hierarchy. See the Object Class page for what that gives you for free (toString(), equals(), hashCode(), and more).
What Gets Inherited?
| Member | Inherited? |
|---|---|
public fields & methods | Yes |
protected fields & methods | Yes |
| Package-private (default) members | Yes, if same package |
private fields & methods | No |
| Constructors | No — but callable via super() |
static members | Inherited (hidden, not overridden) |
Tip: Even though
privatemembers are not directly accessible in the subclass, they still exist inside the inherited object. The subclass can reach them indirectly throughpublic/protectedgetter and setter methods.
Calling the Superclass — super
The super keyword gives you explicit access to the parent class from within the subclass.
Accessing a superclass method
class Vehicle {
void describe() {
System.out.println("I am a vehicle.");
}
}
class Car extends Vehicle {
@Override
void describe() {
super.describe(); // calls Vehicle.describe()
System.out.println("I am a Car.");
}
}
Output:
I am a vehicle.
I am a Car.
Calling a superclass constructor
class Person {
String name;
Person(String name) {
this.name = name;
}
}
class Employee extends Person {
int id;
Employee(String name, int id) {
super(name); // must be the first statement
this.id = id;
}
void display() {
System.out.println("ID: " + id + ", Name: " + name);
}
}
public class Main {
public static void main(String[] args) {
Employee e = new Employee("Alice", 101);
e.display();
}
}
Output:
ID: 101, Name: Alice
Warning: If a superclass defines a constructor with parameters and no no-arg constructor, you must call
super(...)explicitly as the first line of every subclass constructor, or the code won’t compile.
Method Overriding
A subclass can provide its own implementation of an inherited method — this is called method overriding and is the foundation of runtime polymorphism.
class Shape {
double area() {
return 0;
}
}
class Circle extends Shape {
double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
}
public class Main {
public static void main(String[] args) {
Shape s = new Circle(5); // polymorphic reference
System.out.printf("Area: %.2f%n", s.area());
}
}
Output:
Area: 78.54
The @Override annotation is optional but strongly recommended — it makes your intent explicit and lets the compiler catch typos in method signatures.
Multilevel Inheritance
Java allows a chain of inheritance: A → B → C. Each subclass inherits from its immediate parent, which itself may have inherited from its own parent.
class Animal {
void breathe() { System.out.println("Breathing..."); }
}
class Mammal extends Animal {
void feedMilk() { System.out.println("Feeding milk..."); }
}
class Cat extends Mammal {
void meow() { System.out.println("Meow!"); }
}
public class Main {
public static void main(String[] args) {
Cat c = new Cat();
c.breathe(); // from Animal
c.feedMilk(); // from Mammal
c.meow(); // from Cat
}
}
Output:
Breathing...
Feeding milk...
Meow!
There is no practical depth limit, but very deep hierarchies are hard to read and maintain. Favour shallow hierarchies combined with interfaces when possible.
The final Keyword and Inheritance
You can restrict inheritance in two ways using the final keyword:
final class— the class cannot be extended at all (e.g.,Stringisfinal).final method— the method cannot be overridden in any subclass.
final class Utility {
static int square(int n) { return n * n; }
}
// Compilation error — cannot extend a final class
// class MyUtil extends Utility { }
Under the Hood
Object layout and vtable dispatch
When the JVM loads a class, it builds a vtable (virtual method table) — an array of method pointers for every overridable method the class exposes. Each subclass gets its own vtable that copies the parent’s entries and replaces entries for overridden methods.
When you call a virtual method through a reference (e.g., shape.area()), the JVM uses the actual runtime type of the object to look up the correct vtable entry. This is called dynamic dispatch and is what makes polymorphism work. See vtable & Dynamic Dispatch for the full picture.
Memory layout
A subclass object contains the fields of every class in its hierarchy, laid out contiguously on the heap. The JVM prepends an object header (mark word + class pointer, typically 16 bytes) before the field data. Because of this, even an empty subclass is slightly larger than its superclass — the extra space comes from the header, not new fields.
Bytecode: invokespecial vs invokevirtual
The Java compiler generates different bytecode instructions depending on how a method is called:
| Call type | Bytecode instruction |
|---|---|
super.method() | invokespecial (resolved at compile time) |
| Normal virtual call | invokevirtual (resolved at runtime) |
| Static method | invokestatic |
| Interface method | invokeinterface |
invokespecial is used for superclass calls and constructors because the target is known statically — there is no need for vtable lookup. invokevirtual performs the runtime vtable dispatch described above.
The JIT compiler further optimises hot call sites with inline caching and, when the type is monomorphic (only one concrete class seen at that call site), can devirtualise the call entirely — turning the dispatch into a direct call with zero overhead. Read more in JIT Compilation & Bytecode.
Inheritance vs Composition
A common question is: should I extend this class, or hold a reference to it?
| Inheritance (IS-A) | Composition (HAS-A) | |
|---|---|---|
| Relationship | Subtype of parent | Contains an instance |
| Coupling | Tight — breaks if superclass changes | Loose — easy to swap |
| Flexibility | Fixed at compile time | Can swap at runtime |
| Best for | True IS-A relationships | Everything else |
Composition (HAS-A) is covered in depth on the Aggregation page. The classic advice is “favour composition over inheritance” — reach for extends when you genuinely have a subtype relationship, not just because you want to reuse a few methods.
In This Section
- Types of Inheritance — a guided tour of single, multilevel, hierarchical, and hybrid inheritance with diagrams and code examples for each.
- Aggregation (HAS-A) — when one object owns or uses another; the composition alternative to inheritance.
Related Topics
- Polymorphism — inheritance is the mechanism that makes polymorphism possible; see how it all fits together.
- Method Overriding — the full rules for correctly overriding a superclass method, including covariant return types and checked exceptions.
- super Keyword — all the ways
superlets you reach back to the parent class from a subclass. - Abstract Class — how to define a partially-implemented superclass that forces subclasses to fill in the blanks.
- Interface — achieve multiple-inheritance-style flexibility without the diamond problem.
- final Keyword — lock down classes and methods to prevent unwanted extension or overriding.