Exception Handling Best Practices

Naveen AnamaneniUpdated · 5 min read

Exceptions are only as good as the way you use them. Handled well, they make failures obvious, local and easy to fix. Handled badly, they hide bugs, lose the real cause, and turn a two-minute fix into a day of searching. This lesson collects the habits experienced Java developers follow, each with the reason behind it, and ends with a small before-and-after.

The Habits

#HabitWhy
1Validate early, fail fastA bad value rejected at the start, with a clear message, is far easier to trace than a strange failure ten calls later
2Catch specific exceptionscatch (Exception e) also catches bugs you didn't mean to handle
3Never swallow an exceptionAn empty catch makes failures silent; at minimum, log it
4Catch where you can actLow-level code rarely knows the right response; let exceptions propagate to code that does
5Keep the cause when wrappingnew MyException("msg", e) preserves the original stack trace
6Use try-with-resourcesResources are always closed, and closing errors don't hide the real one
7Write useful messagesSay what failed and include the bad value: "Deposit must be positive, got -200"
8Don't use exceptions for normal flowThrowing costs time (the stack trace is captured); an if is clearer and faster
9Prefer standard exceptionsIllegalArgumentException, IllegalStateException and friends are understood instantly
10Don't catch Throwable or ErrorYou'd also catch OutOfMemoryError, which you can't fix by catching
11Log once, at the boundaryLogging and rethrowing at every level prints the same error many times
12Never return from finallyIt discards the try's result and any exception

Before and After

Before.java
public class Before {
    static int parse(String s) {
        try {
            return Integer.parseInt(s);
        } catch (Exception e) {
            return 0;                      // swallowed, and hides real bugs
        }
    }
}
Output
Advitha ordered 3
Rejected: Quantity must be a whole number, got "three"
Rejected: Quantity is required

What changed

  1. Fail fast: blank input is rejected at the start with its own message.
  2. Specific catch: only NumberFormatException is caught, so unrelated bugs still surface.
  3. No swallowing: instead of a silent 0, the caller gets a clear exception it can show to the user.
  4. Cause kept: the original NumberFormatException is attached.
  5. Useful message: it says what was expected and what arrived.

Exceptions Cost Time

Creating an exception records the whole call stack, which is relatively slow. In one run of 200,000 throws, creating normal exceptions took about 70 ms, while the same loop with a plain if check took under 1 ms. That's nothing for real errors, but it's a reason not to use exceptions as ordinary control flow, such as ending a loop.

Common Mistakes

e.printStackTrace() left in production code. Use a logger, which records time, thread and context.

throws Exception everywhere. Declare the specific checked exceptions.

Catching and returning null. The caller then fails later with a NullPointerException far from the real cause.

Interview Corner

What are some exception handling best practices in Java?

Validate inputs early and fail fast with clear messages; catch the most specific exception types, and only where you can respond meaningfully; never leave catch blocks empty; preserve the original exception as the cause when wrapping; use try-with-resources for anything that must be closed; prefer standard exception types; don't use exceptions for normal control flow; don't catch Throwable or Error; log an exception once, at the boundary where it's handled; and never return from a finally block.

Practice

  1. Easy: Find the problems in this code and rewrite it: try { save(order); } catch (Exception e) { }.
  2. Harder: Rewrite a method that returns -1 for "not found" so that it either returns an Optional or throws a custom exception, and explain which you'd choose and why.

Quick check: Best practices

4 questions
1What's wrong with an empty catch block?
2When wrapping an exception, you should:
3Why not use exceptions to end a loop?
4Which is the best place to catch and report most exceptions?

Key Takeaways

Was this tutorial helpful?

Lesson 237 of 482