Chapter 41: Method Overriding in Java
This chapter is only about method overriding: a child class provides a replacement for an instance method inherited from a parent, with rules the compiler enforces. Polymorphism (Chapter 40) is what makes those replacements matter at runtime.
1. Topic title
Overriding: same signature, compatible return, not weaker access, instance methods only—annotate with @Override
2. What it means
class Logger {
void log(String msg) {
System.out.println(msg);
}
}
class TimestampLogger extends Logger {
@Override
void log(String msg) {
super.log(java.time.Instant.now() + " " + msg);
}
}@Override tells the compiler “this must override something.” If you mistype the name or parameters, you get a compile error instead of a silent overload you did not intend.
3. Why it is used
Specialize behavior while keeping the same call site (logger.log("x")).
Catch mistakes early — without @Override, a tiny signature drift creates a new overload and your “override” never runs.
4. Real-world example
UI themes: Widget.draw() overridden per theme; the layout engine calls draw() on Widget references without branching on concrete widget classes everywhere.
5. Java code example
class Account {
protected String id() {
return "acct";
}
void printId() {
System.out.println(id());
}
}
class SavingsAccount extends Account {
@Override
public String id() {
return "sav-" + super.id();
}
}
class Tool {
static void ping() {
System.out.println("tool");
}
}
class Hammer extends Tool {
static void ping() {
System.out.println("hammer");
}
}
public class OverrideDemo {
public static void main(String[] args) {
Account a = new SavingsAccount();
a.printId();
Tool t = new Hammer();
t.ping();
Hammer.ping();
}
}static methods are not overridden in the instance sense—they hide by static type of the reference. t.ping() prints tool because t’s compile-time type is Tool. Hammer.ping() prints hammer.
6. Explanation of code
Instance id() is overridden; printId calls the runtime override through polymorphism. super.id() reaches the parent implementation when you want to extend, not discard, behavior.
7. Common mistakes
Trying to override private methods — they are not visible to the child; you may accidentally define an unrelated method with the same name.
Narrowing access — you cannot make an overridden method more private than the parent’s version.
Forgetting super(...) in constructors when the parent has no default constructor—Chapter 34.
8. Best practices
Always use @Override on intentional overrides.
Keep overrides surprising-behavior-free when the method is part of a contract callers rely on—Liskov intuition: subclasses should remain usable where the parent was promised.
9. Small practice task
Add class CheckingAccount extends Account with @Override String id(). Store it in Account ref = new CheckingAccount(); and print ref.id()—confirm which body runs.
Beginner tip
If two methods “feel” like overrides but only one runs, check static, private, final on parent method, and signatures—those details decide what Java allows and what it dispatches.