Best Practices & Anti-Patterns
Best Practices & Anti-Patterns
You now know how to use every exception mechanism Java offers. This lesson is about using them well. Poor exception handling is one of the most common sources of mysterious bugs, silent data corruption, and production outages. The four principles below — never swallow exceptions, fail fast, catch specific types, and log with context — will make your code trustworthy and your debugging sessions short.
1. Never Swallow Exceptions
Swallowing an exception means catching it and doing nothing — no logging, no rethrow, no recovery. The error disappears silently and the program continues in a broken state.
Why is this dangerous? Suppose loadConfig fails because the file is missing. The program continues with default (or null) values, produces wrong output, and crashes somewhere completely unrelated — making the root cause nearly impossible to find.
The minimal safe alternatives:
Option B is only acceptable when you have a real recovery strategy and you document it clearly.
2. Fail Fast
"Fail fast" means detecting problems as early as possible and stopping immediately rather than allowing bad state to propagate. The longer a program runs with corrupted data, the harder it is to trace the damage back to its source.
Objects.requireNonNull for null checks. It throws a NullPointerException with your message and is instantly recognisable to other developers:
Objects.requireNonNull(order, "order must not be null");
Fail-fast validation is especially critical in constructors and public API methods, where invalid state can spread to many callers.
3. Catch Specific Types — Not Exception or Throwable
Catching a broad type hides all the detail you need to respond correctly.
If processPayment throws a NullPointerException because you forgot to initialise a field, this catch block hides the bug. If it throws an OutOfMemoryError, continuing is actively harmful.
Each branch does the right thing for that specific failure. You cannot do that when everything is an Exception.
Throwable unless you are writing framework infrastructure (e.g., a thread-pool supervisor). Throwable includes Error subclasses like OutOfMemoryError and StackOverflowError — conditions the JVM itself is in trouble with. Swallowing those makes things worse.
4. Log With Context
When an exception does occur, a bare e.getMessage() is rarely enough to diagnose it in production. Always include the values that led to the failure.
Always pass the exception object as the last argument to your logger so the full stack trace is recorded. Stack traces show you the exact line of code that failed — dropping them is like deleting a crash report.
System.out.println. Production logs need levels (DEBUG/INFO/WARN/ERROR), timestamps, thread names, and file rotation. println provides none of that.
Putting It All Together
Here is a realistic method that applies all four principles:
Quick Reference: Anti-Patterns to Avoid
- Empty catch block — exceptions disappear silently.
- Catching
ExceptionorThrowable— masks bugs and JVM errors. - Logging without the exception object — stack trace is lost.
- Logging and rethrowing without wrapping — the same error gets logged twice at every layer.
- Using exceptions for normal flow control — e.g., throwing an exception when a list is empty instead of returning an empty list. Exceptions are slow and semantically wrong for expected outcomes.
- Catching a checked exception just to satisfy the compiler — wrap it in a meaningful unchecked exception instead of swallowing it.
Summary
Good exception handling is not about writing more try/catch blocks — it is about writing intentional ones. Never swallow exceptions; always let failures be visible. Fail fast by validating inputs at the boundary. Catch the most specific type that matches the failure so you can respond correctly. Log with enough context — including the exception object — that a developer can diagnose the problem from the log alone. These habits separate robust, maintainable code from fragile code that silently corrupts state and produces baffling bugs months later.