In Java, exception handling in inheritance follows specific rules to ensure that overridden methods maintain compatibility with the base class in terms of the exceptions they throw. When a subclass overrides a method from its superclass, it must adhere to certain constraints related to checked exceptions.
Core Concepts
1. Checked Exceptions
- A subclass can only throw the same or a subclass of the checked exception declared in the superclass method.
- The subclass cannot throw broader (new or additional) checked exceptions.
2. Unchecked Exceptions
- A subclass method can throw unchecked exceptions (like
NullPointerException
,ArithmeticException
) without restriction, regardless of the superclass method.
3. No Exception in Superclass
- If the superclass method does not declare any checked exception, then the subclass method cannot declare any new checked exception.
- Unchecked exceptions are still allowed.
Example Program Demonstrating Exception Handling in Inheritance
Simulate a Software Engineering designation hierarchy where each role overrides a method performDuties()
that may throw exceptions (e.g., project delivery errors). Show how exception handling rules in inheritance apply.
// Base class class Engineer { public void performDuties() throws java.io.IOException { System.out.println("Engineer is writing code..."); throw new java.io.IOException("Code build failed!"); } } // Subclass throwing same exception class SeniorEngineer extends Engineer { @Override public void performDuties() throws java.io.FileNotFoundException { System.out.println("Senior Engineer is reviewing code..."); throw new java.io.FileNotFoundException("Review document missing!"); } } // Subclass throwing unchecked exception class TeamLead extends Engineer { @Override public void performDuties() throws RuntimeException { System.out.println("Team Lead is managing the project..."); throw new RuntimeException("Project deadline missed!"); } } // Subclass with illegal checked exception (Uncomment to see error) /* class Manager extends Engineer { @Override public void performDuties() throws Exception { // Compile-time error System.out.println("Manager is allocating resources..."); } } */ public class SoftwareTeam { public static void main(String[] args) { Engineer engineer; engineer = new SeniorEngineer(); try { engineer.performDuties(); } catch (java.io.IOException e) { System.out.println("Caught IOException: " + e.getMessage()); } engineer = new TeamLead(); try { engineer.performDuties(); } catch (RuntimeException e) { System.out.println("Caught RuntimeException: " + e.getMessage()); } } } /* Senior Engineer is reviewing code... Caught IOException: Review document missing! Team Lead is managing the project... Caught RuntimeException: Project deadline missed! */
Important Rules
Rule | Explanation |
---|---|
✅ Subclass method can throw same or narrower checked exception | e.g., FileNotFoundException instead of IOException |
❌ Subclass cannot throw broader/new checked exceptions | Leads to compile-time error |
✅ Subclass method can throw unchecked exceptions | No restriction |
❌ If superclass method does not declare checked exceptions, subclass cannot add them | Violates method signature contract |
Exception handling in inheritance ensures that polymorphism works seamlessly and predictably. It enforces that clients depending on a superclass method are not surprised by additional checked exceptions introduced in subclass methods. Following these rules leads to more robust and maintainable object-oriented programs.