Exception Documentation and Handling
Source: Effective Java, 3rd Edition — Chapter 10 by Joshua Bloch (Items 74–77)
This lesson closes Chapter 10: documenting thrown exceptions, rich detail messages, failure atomicity, and why empty catch blocks are dangerous.
Item 74: Document all exceptions thrown by each method
Document every exception a method can throw — checked and unchecked — with @throws in Javadoc (Item 56). Unchecked exceptions describe preconditions; unchecked docs are especially important on interfaces.
Rules:
- Declare each checked exception individually in the method’s
throwsclause — neverthrows Exceptionorthrows Throwable(exceptmain). - Document unchecked exceptions with
@throwsonly — do not list them inthrows(that visual distinction matters). - Class-level docs can cover repeated cases (e.g. “all methods throw
NullPointerExceptionon null args”).
Documenting exceptions
1 / 2public void foo() throws Exception
Pick an answer to see if you are right.
Item 75: Include failure-capture information in detail messages
When something fails in production, the stack trace’s detail message may be the only clue. Include parameter and field values that contributed to the failure:
throw new IndexOutOfBoundsException(
"Index: " + index + ", Size: " + size);
Prefer exception constructors that take structured data and build the message centrally — and expose accessors on checked exceptions for recovery logic. Don’t put secrets (passwords, keys) in messages.
Detail messages are for engineers, not end-user UI copy.
Item 76: Strive for failure atomicity
After a method throws, the object should usually remain usable — in the same state as before the call (failure-atomic).
Techniques:
- Immutable objects — failure atomicity is free.
- Validate before mutate — check preconditions first (
Stack.popcheckssize == 0before--size). - Compute-then-commit — do risky work on a copy, swap in on success.
- Recovery/rollback — rare; mainly for durable structures.
Document when atomicity cannot be guaranteed (e.g. after ConcurrentModificationException).
Failure atomicity
1 / 2Stack.pop decrements size before checking empty
Pick an answer to see if you are right.
Item 77: Don’t ignore exceptions
An empty catch block silences failures and makes debugging nightmares — the program may fail later, far from the root cause.
// Don't
try {
...
} catch (SomeException e) {
}
// Rare OK: comment why, name variable ignored
} catch (IOException ignored) {
// already read everything needed; close failure is harmless
}
Prefer handling, propagating, or logging. Applies to checked and unchecked exceptions.
Items 74–77 map
| Item | Move |
|---|---|
| 74 | @throws every exception; throws only checked |
| 75 | Detail messages capture failing parameter values |
| 76 | Validate before mutate; object usable after failure |
| 77 | Never empty catch; propagate, handle, or log |
Chapter 10 complete. Next: Concurrency (Chapter 11, Items 78–81).