Checked vs Unchecked Exceptions in Java – Explained with Examples
Java divides exceptions into two groups based on whether the compiler checks that you handle them. Checked exceptions must be caught or declared, or your code will not compile. Unchecked exceptions can be thrown anywhere without any declaration. This design decision affects how you write methods, how you design APIs, and how you deal with errors in lambdas and streams.
This tutorial explains both groups, shows them in action, compares them side by side, and gives practical guidance on which to use.
1. Which Exceptions Are Checked?
- Unchecked:
RuntimeExceptionand all its subclasses, plusErrorand its subclasses. - Checked: every other subclass of
Exception(andThrowableitself).
2. Checked Exceptions: Catch or Declare
The compiler enforces the catch-or-declare rule for checked exceptions. Calling a method that throws one without handling it is a compile error:
Bad.java:2: error: unreported exception IOException; must be caught or declared to be thrown
public class Bad { public static void main(String[] a) { System.out.println(Files.size(Path.of("x"))); } }
^
1 error
Declaring it with throws and catching it in the caller satisfies the rule:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class CheckedDemo {
// Checked: the compiler forces callers to deal with IOException
static long fileSize(String name) throws IOException {
return Files.size(Path.of(name));
}
public static void main(String[] args) {
try {
System.out.println(fileSize("does-not-exist.csv"));
} catch (IOException e) {
System.out.println("Handled checked exception: " + e.getClass().getSimpleName());
}
}
}
Handled checked exception: NoSuchFileException
3. Unchecked Exceptions: Fix the Cause
Unchecked exceptions compile without any handling. They usually point to a bug or invalid input, so the best response is often to prevent them with a check rather than to catch them:
import java.util.List;
public class UncheckedDemo {
// Unchecked: compiles without try-catch or throws; fails only at runtime
static String thirdItem(List<String> items) {
return items.get(2);
}
public static void main(String[] args) {
System.out.println(thirdItem(List.of("a", "b", "c")));
// Better than catching: prevent the bug with a check
List<String> shortList = List.of("a");
if (shortList.size() > 2) {
System.out.println(thirdItem(shortList));
} else {
System.out.println("List too short, no third item");
}
try {
thirdItem(shortList);
} catch (IndexOutOfBoundsException e) {
System.out.println("Unchecked exception at runtime: " + e.getMessage());
}
}
}
c List too short, no third item Unchecked exception at runtime: Index: 2 Size: 1
4. Checked vs Unchecked: Comparison
| Aspect | Checked | Unchecked |
|---|---|---|
| Extends | Exception (not RuntimeException) | RuntimeException (or Error) |
| Checked by compiler | Yes: catch or declare | No |
throws clause | Required if not caught | Optional |
| Typical cause | External conditions: files, network, database, interruption | Programming errors or invalid arguments |
| Can the caller recover? | Usually, in some way | Usually by fixing the code |
| Examples | IOException, SQLException, InterruptedException, ClassNotFoundException | NullPointerException, IllegalArgumentException, ArithmeticException, IndexOutOfBoundsException |
| Works smoothly in lambdas | No | Yes |
5. Checked Exceptions and Lambdas
Standard functional interfaces such as Function do not declare checked exceptions, so a lambda cannot throw one. The common workaround is to wrap it in an unchecked exception, such as UncheckedIOException, and unwrap it outside:
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.List;
public class WrapChecked {
static String load(String name) throws IOException {
if (name.startsWith("x")) throw new IOException("cannot read " + name);
return name.toUpperCase();
}
public static void main(String[] args) {
List<String> names = List.of("alpha", "beta", "xray");
try {
// Lambdas in streams cannot throw checked exceptions: wrap them in an unchecked one
List<String> loaded = names.stream()
.map(n -> {
try {
return load(n);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
})
.toList();
System.out.println(loaded);
} catch (UncheckedIOException e) {
System.out.println("Stream failed: " + e.getCause().getMessage());
}
}
}
Stream failed: cannot read xray
6. Which Should You Use?
- Use a checked exception when the caller can reasonably recover and you want the compiler to remind every caller, for example a file that may not exist in a desktop tool.
- Use an unchecked exception for programming errors (bad arguments, wrong state), and when callers usually cannot do anything except report the error.
- Many modern frameworks (Spring, Hibernate, most cloud SDKs) prefer unchecked exceptions and handle them centrally, translating checked JDK exceptions where needed.
- Whatever you choose, document it with Javadoc
@throws.
7. The Debate in Brief
Supporters of checked exceptions say they make failure modes explicit and impossible to forget. Critics say they create boilerplate, encourage empty catch blocks, leak implementation details through throws clauses, and clash with lambdas. Java itself keeps them, while newer JVM languages such as Kotlin and Scala treat all exceptions as unchecked.
8. Summary
- Checked exceptions extend
Exception(notRuntimeException) and must be caught or declared. - Unchecked exceptions extend
RuntimeExceptionorErrorand need no handling by rule. - Checked exceptions usually represent external, recoverable conditions; unchecked ones usually represent bugs.
- In lambdas, wrap checked exceptions in unchecked ones such as
UncheckedIOException. - Choose based on whether callers can reasonably recover.
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is a checked exception?
An exception that the compiler checks: if code can throw it, the code must catch it or declare it with throws. Examples include IOException and SQLException.
Q2. What is an unchecked exception?
An exception the compiler does not check: RuntimeException, Error and their subclasses. Examples include NullPointerException and ArithmeticException.
Q3. Why are they called checked and unchecked?
Because the compiler checks at compile time whether checked exceptions are handled, while unchecked exceptions are not checked.
Q4. Do both types occur at runtime?
Yes. All exceptions are thrown while the program runs. "Checked" only refers to the compile-time verification of handling, not to when they happen.
Q5. Is NullPointerException checked or unchecked?
Unchecked. It extends RuntimeException.
Q6. Is FileNotFoundException checked or unchecked?
Checked. It is a subclass of IOException.
Q7. Is Exception itself checked?
Yes. Throwing new Exception() requires a throws Exception declaration or a catch block.
Q8. Why doesn't Java force us to handle unchecked exceptions?
They can occur almost anywhere (any method call might hit a null), so forcing handling would clutter all code. Instead they should be prevented by correct programming.
Q9. Can I convert a checked exception into an unchecked one?
Yes, by catching it and throwing an unchecked exception with the original as its cause, for example throw new UncheckedIOException(e); or a custom RuntimeException.
Q10. Why can't lambdas throw checked exceptions?
Because the abstract methods of standard functional interfaces (Function.apply, Consumer.accept and so on) do not declare any checked exceptions.
Q11. Should my custom exceptions be checked or unchecked?
Checked if callers can and should handle them explicitly; unchecked if they represent programming errors or are handled centrally, which is common in modern applications.
Q12. Is InterruptedException checked?
Yes. When you catch it and do not rethrow, restore the interrupt flag with Thread.currentThread().interrupt().
Q13. Is SQLException checked?
Yes. Frameworks like Spring translate it into an unchecked DataAccessException hierarchy.
Q14. Can an overriding method throw a new checked exception?
No. It may throw the same, narrower or no checked exceptions, but not new or broader ones. Unchecked exceptions are always allowed.
Q15. Are errors checked exceptions?
No. Error and its subclasses are unchecked, and they are not exceptions in the Exception sense at all.
Q16. Do other languages have checked exceptions?
Java is almost unique in this. C#, Kotlin, Scala and Python treat all exceptions as unchecked.
Q17. Is catching RuntimeException a good idea?
Only at application boundaries for logging and error responses. Inside business logic, prefer preventing runtime exceptions or catching specific ones.
Q18. Which is more common in modern Java code?
Unchecked exceptions for application code, while checked exceptions remain common in JDK I/O, networking and JDBC APIs.
Q19. Does catching a checked exception the try block can't throw compile?
No. The compiler reports that the exception is never thrown in the try block. This check does not apply to unchecked exceptions or to Exception.
Q20. What is UncheckedIOException?
A JDK runtime exception (Java 8+) that wraps an IOException, used when I/O errors must cross code that cannot throw checked exceptions, such as streams.