Exception Propagation in Java
When a method throws an exception and doesn't catch it, the exception doesn't just disappear. It leaves that method and appears in the caller, at the line that made the call. If the caller doesn't catch it either, it leaves the caller too, and so on, back up the chain of calls. This trip back through the callers is called propagation. Understanding it explains where to put your catch blocks and how to read a stack trace.
Watching It Travel
public class Propagate {
static int average(int[] marks) {
int sum = 0;
for (int m : marks) {
sum += m;
}
System.out.println(" average: dividing " + sum
+ " by " + marks.length);
return sum / marks.length;
}
static void printReport(String name, int[] marks) {
System.out.println(" printReport: " + name);
System.out.println(" " + name + " averages " + average(marks));
System.out.println(" printReport finished");
}
public static void main(String[] args) {
try {
printReport("Navika", new int[] {80, 90});
printReport("Srihitha", new int[] {});
System.out.println("all reports done");
} catch (ArithmeticException e) {
System.out.println("main caught: " + e.getMessage());
}
System.out.println("main continues");
}
} printReport: Navika
average: dividing 170 by 2
Navika averages 85
printReport finished
printReport: Srihitha
average: dividing 0 by 0
main caught: / by zero
main continuesHow it works
- For Navika, every method finishes normally.
- For Srihitha,
averagedivides by zero and throwsArithmeticException. It has nocatch, soaverageends right there. - The exception appears in
printReport, at the call toaverage. It has nocatcheither, so"Srihitha averages"and"printReport finished"never print. - The exception appears in
main, inside itstry. The matchingcatchhandles it, and"all reports done"is skipped too. maincontinues normally after thecatch.
Checked Exceptions Need Permission
Unchecked exceptions, like the ArithmeticException above, propagate freely. A checked exception may only leave a method that declares it with throws (see "Java Throws Keyword"). So for checked exceptions, propagation is visible in every method signature along the way, which is exactly the point: callers are warned.
| Kind | Can propagate out of a method... |
|---|---|
Unchecked (RuntimeException, Error) | Always, with no declaration |
| Checked | Only if the method declares it with throws |
Where Should the catch Go?
Propagation lets you choose the level at which to handle a problem. Usually that's the highest level that still knows what to do: a web request handler shows an error page, a batch job skips one record, a UI shows a message. Low-level methods like average usually shouldn't catch at all; they don't know what the right response is.
Common Mistakes
Catching too low. A method that catches and prints, then returns a fake value, hides the problem from callers who could have handled it properly.
Expecting code after the failing call to run. Every statement after the call in each method being left is skipped.
Forgetting throws for a checked exception you want to propagate. The code won't compile.
Interview Corner
What is exception propagation?
When an exception is thrown and not caught in the current method, the method terminates and the exception is passed to its caller at the point of the call. This repeats up the call stack until a matching catch block handles it. If it reaches the top of the thread's stack uncaught, the thread terminates and the default handler prints the stack trace. Unchecked exceptions propagate automatically; checked exceptions must be declared with throws to propagate.
Practice
- Easy: Add a
try-catchinsideprintReportinstead ofmain. What changes in the output, and does"all reports done"print now? - Harder: Make
averagethrow a checked exception of your own for an empty array. Which method signatures must change?
Key Takeaways
Was this tutorial helpful?