Checked vs unchecked exceptions
The compiler rules for checked and unchecked exceptions, the long-running debate and a practical default, wrapping with cause chains, checked exceptions inside lambdas, sneaky throw, and throws rules for overriding methods.
On this page
⚖️ What are checked and unchecked exceptions?
A checked exception is one the compiler makes you deal with: if a method can throw IOException, every caller must either catch it or declare throws IOException. An unchecked exception (RuntimeException, Error and their subclasses) has no such rule. Files.readString(path) forces you to think about a missing file, while Integer.parseInt("abc") can throw NumberFormatException without the compiler saying a word.
This is the most-asked exception question in Java interviews, and the reason is simple: the rule takes ten seconds to state, but the design question behind it ("which one would you use, and why?") has no single right answer. Java is almost alone among popular languages in having checked exceptions, and even the JDK uses them inconsistently. An interviewer wants to see that you know the compiler rules cold and that you have a defensible opinion.
What you’ll learn
- State exactly which exceptions are checked and what "catch or declare" requires, including the never-thrown
catcherror - Explain why checked exceptions are a compile-time-only rule and how sneaky throw exploits it
- Choose between checked, unchecked and result types with a defensible default
- Translate exceptions between layers without losing the cause chain
- Handle checked exceptions inside lambdas and streams with
UncheckedIOExceptionor a throwing interface - Apply the throws rules for overriding: same, narrower or none, never broader
For this lesson, we'll focus on the compiler rules, the long-running debate, a practical way to choose, wrapping exceptions without losing the cause, the pain of checked exceptions inside lambdas, the "sneaky throw" trick that proves checked exceptions only exist in javac, and the rules for throws clauses when you override a method.
Below the line (out of scope)
- How exceptions are thrown and caught at the bytecode level: How exceptions work in Java
- Designing custom exception hierarchies: Custom exceptions and best practices
- Exceptions in
CompletableFuturepipelines: Concurrency module
The 30-second answer
Checked exceptions are every Throwable except RuntimeException, Error and their subclasses. The compiler enforces "catch or declare" for them, and that's the only difference: the JVM doesn't know or care, which is why tricks like sneaky throw work. I use checked exceptions when the immediate caller can realistically recover (retry, fall back, ask the user), and unchecked for programming errors and for failures that will only be handled at a generic boundary. When I translate between layers, I wrap and always pass the original as the cause. Lambdas can't throw checked exceptions through Function or Consumer, so I wrap them in UncheckedIOException or use a throwing functional interface. An overriding method may throw fewer or narrower checked exceptions, never new or broader ones.
Interview radar
Asked very often: What is the difference between checked and unchecked exceptions, with examples of each, and which do you prefer?
Senior rounds probe: Why can't a lambda passed to stream().map() throw IOException, what is sneaky throw, and what are the throws rules for overriding methods?
Production angle: A wrapped exception that drops its cause, so the logs say "order lookup failed" and the real SQLException is gone.
01Picture it first: a signed delivery versus a dropped parcel
Think of a checked exception as a parcel that needs a signature. The courier (the compiler) won't leave it at your door: somebody in the call chain has to sign for it, either by handling it (catch) or by explicitly forwarding it (throws). An unchecked exception is a parcel thrown over the fence. Nobody was forced to sign, so it lands wherever it lands, usually at the request handler at the top of the stack.
Neither one is "better". A signature is useful when the receiver can do something with the parcel, and tedious when everyone in the chain forwards it without opening it, which is exactly the complaint people have about checked exceptions.
The diagram below is the decision path I use when I design a method and have to choose.
Decision tree: if the failure is a programming error such as a null argument or illegal state, throw an unchecked exception like IllegalArgumentException; otherwise, if the immediate caller can realistically recover by retrying, falling back or asking the user, use a checked exception or a result type; if not, use an unchecked exception that wraps the cause and let a boundary handler deal with it
02Under the hood: the compiler rules
Try it yourself first
Before reading on: which of these three methods fail to compile, and with what error?
String loadInvoice(Path path) {
return Files.readString(path); // 1
}
void validate(int quantity) {
if (quantity <= 0) throw new IllegalArgumentException("quantity must be > 0"); // 2
}
void ping() {
try {
System.out.println("ping");
} catch (IOException e) { // 3
System.out.println("never happens");
}
}
Premium lesson
Keep reading with the Java Pass
The rest of this lesson is part of Java One-Stop Interview Prep: in-depth explanations, diagrams, model answers and how to say them in the interview.
- The debate, and the default I recommend
- Real world: wrapping without losing the cause
- Advanced: lambdas and checked exceptions
- How to say it in the interview
From ₹199 · one-time payment · No auto-renewal
Further reading (9)
- JLS §11.1.1 and §11.2: The Kinds of Exceptions, Compile-Time Checking of Exceptions
- JLS §8.4.8.3: Requirements in Overriding and Hiding
- JLS §18.4: Resolution (throws inference to RuntimeException)
- JVMS §4.7.5: The Exceptions Attribute
- Oracle Java Tutorials: Unchecked Exceptions, The Controversy
- UncheckedIOException (Java SE 21 Javadoc)
- Effective Java, 3rd ed., Items 70 to 77 (Exceptions)
- Spring Framework: DAO support and consistent exception hierarchy
- Baeldung: Checked and Unchecked Exceptions in Java