Exceptions
Source: Effective Java, 3rd Edition — Chapter 10 by Joshua Bloch (Items 69–73)
Used well, exceptions improve readability and reliability. Used as control flow or leaked implementation details, they do the opposite. This lesson: when to throw, checked vs unchecked, standard types, and exception translation.
Item 69: Use exceptions only for exceptional conditions
Never loop by catching ArrayIndexOutOfBoundsException or NoSuchElementException — it’s obscure, slow, and can swallow unrelated bugs.
// Don't
try {
int i = 0;
while (true)
range[i++].climb();
} catch (ArrayIndexOutOfBoundsException ignored) { }
// Do
for (Mountain m : range)
m.climb();
APIs should offer state-testing methods (Iterator.hasNext) or Optional (Item 55) so clients aren’t forced into exception-driven control flow.
Exceptions vs control flow
1 / 2Iterator lacks hasNext(); clients catch NoSuchElementException to end loops
Pick an answer to see if you are right.
Item 70: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors
Three throwable families:
| Kind | When | Caller expectation |
|---|---|---|
Checked (Exception subclass, not RuntimeException) | Recoverable conditions | Handle or declare |
Runtime (RuntimeException) | Programming errors, precondition violations | Usually don’t catch |
| Error | JVM/resource catastrophe | Don’t throw new subclasses |
ArrayIndexOutOfBoundsException = bad index (client bug). Insufficient funds on gift card = checked exception with recovery info (e.g. shortfall amount).
When unsure, prefer unchecked. Don’t define throwables outside Exception / RuntimeException / Error. Never parse exception strings for data — add accessor methods on checked exceptions.
Checked vs unchecked
1 / 2Method rejects null where null is forbidden
Pick an answer to see if you are right.
Item 71: Avoid unnecessary use of checked exceptions
Checked exceptions force handling — good when recovery is real, painful when callers only do printStackTrace() or throw new AssertionError().
Remedies:
- Return
Optional.empty()instead of throwing when absence is ordinary (Item 55). - Split into
actionPermitted+actionso the happy path need not sit intry(watch concurrency and duplicated work).
Single checked exceptions are especially costly — they block stream usage (Items 45–48).
Item 72: Favor the use of standard exceptions
Reuse library exceptions when semantics match:
| Exception | Use when |
|---|---|
IllegalArgumentException | Bad non-null argument value |
IllegalStateException | Object state wrong for this call |
NullPointerException | Null where prohibited |
IndexOutOfBoundsException | Bad index into sequence |
ConcurrentModificationException | Detected unsynchronized mutation |
UnsupportedOperationException | Optional operation not implemented |
Don’t throw Exception, RuntimeException, Throwable, or Error directly — too broad to catch meaningfully.
Deck deal example: hand size too big because deck is nearly empty → IllegalStateException if no argument would work; IllegalArgumentException if a smaller hand size would work.
Standard exceptions
1 / 2Append-only List.remove(index) is invoked
Pick an answer to see if you are right.
Item 73: Throw exceptions appropriate to the abstraction
Don’t leak low-level exceptions (NoSuchElementException from a ListIterator) through high-level APIs. Translate to types your abstraction promises:
public E get(int index) {
ListIterator<E> i = listIterator(index);
try {
return i.next();
} catch (NoSuchElementException e) {
throw new IndexOutOfBoundsException("Index: " + index);
}
}
Use exception chaining (new HigherLevelException(cause)) so debuggers still see the root cause via getCause(). When you can prevent lower-level failures (validate parameters) or recover silently (log and continue), prefer that over translation.
Items 69–73 map
| Item | Move |
|---|---|
| 69 | Exceptions for failures, not loops; hasNext / Optional |
| 70 | Checked = recoverable; runtime = precondition bugs |
| 71 | Optional or state-test to avoid pointless checked exceptions |
| 72 | Reuse IllegalArgumentException, IllegalStateException, … |
| 73 | Translate lower-level exceptions to abstraction-level types |
Next: Exception Documentation and Handling (Items 74–77).