Rules of Method Overriding
An overriding method makes a promise: anywhere the parent's method could be called, the child's version can be called instead, safely. Every rule of overriding follows from that one promise. The child may do more for the caller (accept a wider audience, return something more specific, throw fewer problems), but never less. Interviewers ask for this list constantly, so learn it through the reason, not by rote.
The Rules at a Glance
| Part of the method | Rule for the overriding method |
|---|---|
| Name and parameter list | Must be exactly the same (otherwise it's an overload) |
| Return type | Same type, or a subtype for reference types (covariant return). Primitives must match exactly |
| Access modifier | Same or wider: protected can become public; public can't become protected |
| Checked exceptions | None, the same, or narrower ones. No new or broader checked exceptions |
| Unchecked exceptions | Any; they're not checked by the compiler |
final methods | Can't be overridden |
static methods | Can't be overridden; a same-signature static method in the child hides the parent's |
private methods | Can't be overridden; they aren't visible to the child |
| Constructors | Can't be overridden; they aren't inherited |
Breaking the Rules
Each method in SalesReport below breaks one rule:
class Report {
public String title() { return "Report"; }
String load() throws java.io.IOException { return ""; }
final String id() { return "R1"; }
int pages() { return 1; }
}
class SalesReport extends Report {
String title() { return "Sales"; }
String load() throws Exception { return ""; }
String id() { return "S1"; }
long pages() { return 2; }
}Rules.java:8: error: title() in SalesReport cannot override title() in Report
String title() { return "Sales"; }
^
attempting to assign weaker access privileges; was public
Rules.java:9: error: load() in SalesReport cannot override load() in Report
String load() throws Exception { return ""; }
^
overridden method does not throw Exception
Rules.java:10: error: id() in SalesReport cannot override id() in Report
String id() { return "S1"; }
^
overridden method is final
Rules.java:11: error: pages() in SalesReport cannot override pages() in Report
long pages() { return 2; }
^
return type long is not compatible with int
4 errorsWhy each rule exists
- Weaker access (line 8): code that calls
report.title()from another package relies on it beingpublic. If the child made it package-private, that call would break forSalesReportobjects. - Broader exception (line 9): callers of
load()were told to handle onlyIOException. A child throwing anyExceptionwould surprise them. - Final (line 10):
finalmeans "this behavior is fixed"; the parent's author forbade overriding. - Return type (line 11): callers expect an
int. Alongdoesn't fit, and primitive return types have no subtypes.
What an Override May Do
import java.io.FileNotFoundException;
import java.io.IOException;
public class Allowed {
static class Report {
protected Object build() throws IOException {
return "report";
}
}
static class SalesReport extends Report {
@Override
public String build() throws FileNotFoundException {
return "Sales report by Advitha";
}
}
public static void main(String[] args) throws IOException {
Report r = new SalesReport();
System.out.println(r.build());
System.out.println(new SalesReport().build().length());
}
}Sales report by Advitha
23How it works
- Access widened:
protectedbecamepublic. Everyone who could call it before still can. - Return type narrowed:
ObjectbecameString(a covariant return type, its own lesson). Through aSalesReportvariable,build()returns aString, so.length()works without a cast. - Exception narrowed:
FileNotFoundExceptionis a subclass ofIOException, so callers who handleIOExceptionare still covered.
Common Mistakes
Reducing access when overriding. Interface methods are implicitly public, so their implementations must be public too; leaving out public is a very common compile error.
Adding a checked exception in the override. Wrap it in an unchecked exception or handle it inside the method.
Thinking a same-signature static method overrides. It hides; see "Can Static, Private and Final Methods Be Overridden".
Interview Corner
What are the rules of method overriding in Java?
The overriding method must have the same name and parameter list. Its return type must be the same or a subtype (covariant), and primitives must match exactly. Its access must be the same or wider. It may throw fewer, narrower or no checked exceptions, but not new or broader ones; unchecked exceptions are unrestricted. Final, static and private methods, and constructors, can't be overridden.
Can an overriding method throw an exception the parent method doesn't throw?
Only if it's unchecked, such as IllegalStateException. A new or broader checked exception isn't allowed, because callers written against the parent method wouldn't be prepared to handle it.
Practice
- Easy: For each change to
protected Number total() throws IOException, say allowed or not:public Integer total();Number total();protected Number total() throws Exception;protected Number total(). - Harder: Write an interface
GreeterwithString greet(String name), implement it without the wordpublic, read the compile error, then fix it.
Key Takeaways
Was this tutorial helpful?