Inheritance in Java β <code>extends</code> and <code>super</code>
Inheritance is a Java mechanism for reusing and specialising an existing class. A subclass gets all non-private members of its parent and can add new ones or override existing behaviour. Java allows single inheritance only β a class extends at most one other class β but can implement any number of interfaces.
Basic syntax
public class Animal {
protected String name;
public Animal(String name) { this.name = name; }
public String speak() { return name + " makes a sound"; }
}
public class Dog extends Animal {
private final String breed;
public Dog(String name, String breed) {
super(name); // call parent constructor
this.breed = breed;
}
@Override
public String speak() {
return name + " barks"; // overrides Animal.speak
}
}
What's inherited
| Member | Inherited? |
|---|---|
public, protected methods | β |
public, protected fields | β |
| Package-private methods/fields (same package only) | β (same package) |
private members | β |
| Constructors | β (must call with super(...)) |
static methods | Inherited but not overridden β hidden if redefined |
Constructor chaining
The first statement of every constructor is an implicit or explicit super(...) call. If the parent has no no-arg constructor, you must call super(...) explicitly with arguments.
Overriding rules
- Same name and parameter list as the parent method.
- Return type must be the same or a subtype (covariant return).
- Cannot be more restrictive in access (a
protectedmethod can be overridden topublic, not toprivate). - Cannot throw new or broader checked exceptions.
- Always use
@Overrideβ the compiler catches typo-overrides that silently create new methods.
final, abstract, sealed
public final class Money { ... } // can't be subclassed
public abstract class Shape { ... } // must be subclassed, can't instantiate
public sealed class Shape permits Circle, Square {} // Java 17+ β closed hierarchy
Favour composition
Inheritance models is-a ("a Dog is an Animal"). Most reuse relationships are actually has-a β a Car has an Engine, not is. Use composition (a field + delegation) unless the is-a is literal and the parent is designed for extension.
// Composition β flexible, decoupled
public class Car {
private final Engine engine;
public Car(Engine engine) { this.engine = engine; }
public void start() { engine.ignite(); }
}
Common mistakes
- Missing
@Overrideβ a typo creates a parallel method. Always annotate. - Protected fields β breaks encapsulation. Keep fields private; expose protected methods if subclasses truly need access.
- Deep hierarchies β three levels is usually too many. Prefer composition or interfaces.
- Calling overridable methods from a constructor β subclass override runs before the subclass is fully initialised. Make such methods
final.
Related
Pillar: OOP in Java. Siblings: polymorphism, abstraction, sealed classes.