Catching and rethrowing exceptions in subclasses

In Java, a subclass can catch an exception thrown by a superclass method and then rethrow the same exception or throw a new one. This mechanism allows subclasses to:

  • Perform additional processing (e.g., logging, wrapping).
  • Convert one exception type to another.
  • Propagate errors up the call stack after handling.

Important Concepts

Concept Explanation
Catch and Rethrow Catch the exception using try-catch and use throw to rethrow it.
Preserve Original Exception Use throw e; to maintain the original stack trace.
Wrap in Custom Exception You can wrap the caught exception inside another (custom) exception.
Use throws in method signature Required if you rethrow a checked exception.

Example Program: Catching and Rethrowing in Subclass

import java.io.IOException;

// Superclass
class Employee {
    public void performTask() throws IOException {
        throw new IOException("I/O error in task");
    }
}

// Subclass that catches and rethrows
class SoftwareEngineer extends Employee {
    @Override
    public void performTask() throws IOException {
        try {
            super.performTask();
        } catch (IOException e) {
            System.out.println("Logging in SoftwareEngineer: " + e.getMessage());
            // Rethrow the original exception
            throw e;
        }
    }
}

// Subclass that wraps and rethrows
class TechLead extends Employee {
    @Override
    public void performTask() throws IOException {
        try {
            super.performTask();
        } catch (IOException e) {
            System.out.println("Logging in TechLead: " + e.getMessage());
            // Wrapping original exception in a custom unchecked exception
            throw new RuntimeException("TechLead failed to complete task", e);
        }
    }
}

public class RethrowExample {
    public static void main(String[] args) {
        Employee e1 = new SoftwareEngineer();
        try {
            e1.performTask();
        } catch (IOException ex) {
            System.out.println("Handled in main (SoftwareEngineer): " + ex.getMessage());
        }

        Employee e2 = new TechLead();
        try {
            e2.performTask();
        } catch (RuntimeException ex) {
            System.out.println("Handled in main (TechLead): " + ex.getMessage());
        }
    }
}
/*
Logging in SoftwareEngineer: I/O error in task
Handled in main (SoftwareEngineer): I/O error in task
Logging in TechLead: I/O error in task
Handled in main (TechLead): TechLead failed to complete task
*/

Catching and rethrowing exceptions in subclasses enables fine-grained control over error handling. It allows:

  • Logging or preprocessing before propagating the error.
  • Wrapping exceptions to create more meaningful or domain-specific messages.
  • Maintaining clear exception hierarchies and stack trace context.

This technique is widely used in layered architectures (e.g., service → controller → UI) for robust exception management.

Scroll to Top