Inheritance Is "Is-A" Reuse
Inheritance lets a new class build on an existing one. The new class - the subclass - automatically gets the fields and methods of the superclass, then adds or changes whatever it needs. You reach for it when one type is a more specific kind of another: a Dog is an Animal, a SavingsAccount is a BankAccount.
You write it with the extends keyword. Everything public or protected in the parent is available in the child without rewriting it.
Dog never declares name or eat(), yet it has both. That is the whole point: shared behavior lives in one place.
super: Reaching the Parent
A subclass constructor must make sure the parent is set up first. You do that with super(...), which calls the parent's constructor and must be the first statement in the subclass constructor. If you leave it out, Java inserts a silent call to the parent's no-argument constructor - and if the parent has no such constructor, the code won't compile.
The output shows the parent constructor runs before the child's body - construction flows from the top of the hierarchy down.
Overriding Methods
A subclass can replace an inherited method by redefining it with the same signature. This is overriding, and you should always tag it with @Override. The annotation isn't required, but it makes the compiler verify you actually matched a parent method - it catches typos like tostring() instead of toString() that would otherwise silently create a brand-new method.
Even though the array is typed Animal, each element runs its own speak(). Java picks the method based on the real object at runtime, not the variable's declared type - that's the foundation of polymorphism.
Calling the Parent's Version with super.method()
Overriding doesn't have to throw away the parent's work. Use super.method() to run the inherited version and then add to it:
Without super., calling log inside TimestampLogger.log would call itself and recurse forever. super. explicitly means "the parent's version."
Inherited Fields and Access
A subclass sees the parent's public and protected members but not its private ones. private fields still exist in the object - the parent's own methods can touch them - but the subclass cannot reference them directly. Use protected, one of Java's access modifiers, when you want subclasses to have access while keeping a member hidden from unrelated code.
class Base {
private int secret; // invisible to subclasses
protected int shared; // visible to subclasses
}
class Derived extends Base {
void demo() {
shared = 5; // OK
// secret = 5; // compile error - private to Base
}
}
This is also why a subclass constructor often must call super(...): it's the only way to initialize the parent's private state.
Stopping Inheritance with final
Sometimes a class should not be extended at all - String is final for exactly this reason. Marking a class final forbids subclassing; marking a method final forbids overriding it while still allowing the class to be extended.
final class Constants { } // cannot be subclassed
class Config {
final void load() { } // subclasses may extend Config
// but cannot override load()
}
Reach for final when a class's behavior must be guaranteed and immutable across the program - it's a deliberate "do not extend" signal, not the default.
A Common Gotcha: Favor Composition When It's Not "Is-A"
Inheritance is tempting because it reuses code, but it tightly couples the child to the parent. If the relationship isn't a genuine "is-a" - say a Car that happens to need an Engine - don't make Car extends Engine. A car has an engine, it isn't one. Model that with a field (composition) instead:
class Car {
private Engine engine = new Engine(); // Car HAS-A Engine
void start() { engine.ignite(); }
}
Use inheritance only when the subclass truly is a specialized form of the superclass and you want to inherit and substitute its behavior.
Next: Interfaces
Inheritance with extends gives you a single parent and shared implementation. But a class can extend only one class - so how do you give unrelated classes a common capability? That's what interfaces are for: a contract many classes can implement, and the topic of the next page.
Frequently Asked Questions
What is inheritance in Java?
Inheritance lets one class (the subclass) reuse the fields and methods of another class (the superclass) using the extends keyword. The subclass automatically gets the parent's public and protected members and can add new ones or replace inherited behavior by overriding. It models an "is-a" relationship: a Dog is an Animal.
What does the super keyword do in Java?
super refers to the parent class. super(...) in a constructor calls the parent's constructor (and must be the first statement), while super.method() calls the parent's version of a method you have overridden. It lets a subclass build on the parent's logic instead of replacing it entirely.
What is the difference between overriding and overloading in Java?
Overriding redefines an inherited method in a subclass using the same signature, changing the behavior - mark it with @Override. Overloading defines multiple methods with the same name but different parameter lists in the same class. Overriding is about inheritance and runtime dispatch; overloading is just two methods that happen to share a name.