Checked vs Unchecked Exceptions
Java classifies exceptions into Checked and Unchecked to enforce compile-time safety where appropriate and allow runtime flexibility where necessary. Understanding this distinction is critical for API design, robust code, and interviews.
What Are Checked Exceptions?
Checked exceptions are exceptions that are checked by the compiler at compile time.
Key Characteristics
- Checked at compile time
- Must be handled using try-catch or declared using throws
- Represent recoverable conditions
- Usually related to external systems (I/O, DB, network)
Examples
- IOException
- SQLException
- ClassNotFoundException
- FileNotFoundException
Example
void readFile() throws IOException {
FileReader fr = new FileReader("data.txt");
}
❌ Compile-time error if not handled or declared
✔ Forces developer to think about recovery
What Are Unchecked Exceptions?
Unchecked exceptions are not checked by the compiler and occur at runtime.
Key Characteristics
- Occur at runtime
- Compiler does not force handling
- Usually caused by programming errors
- Extend RuntimeException
Examples
- NullPointerException
- ArithmeticException
- ArrayIndexOutOfBoundsException
- NumberFormatException
Example
int a = 10 / 0; // ArithmeticException
✔ Compiles successfully
❌ Fails at runtime
Exception Hierarchy (Important)
Throwable
├── Exception
│ ├── Checked Exceptions (IOException, SQLException)
│ └── RuntimeException (Unchecked)
│ ├── NullPointerException
│ ├── ArithmeticException
│ └── IndexOutOfBoundsException
└── Error
Core Differences: Checked vs Unchecked (Interview Favorite)
| Aspect | Checked Exceptions | Unchecked Exceptions |
|---|---|---|
| Compiler check | ✅ Yes | ❌ No |
| When detected | Compile time | Runtime |
| Must handle | ✅ Yes | ❌ No |
| Parent class | Exception | RuntimeException |
| Cause | External / Recoverable | Programming bugs |
| API usage | Mandatory handling | Optional handling |
Handling Requirements
Checked Exception — Mandatory
try {
FileReader fr = new FileReader("file.txt");
} catch (IOException e) {
e.printStackTrace();
}
OR
void method() throws IOException { }
Unchecked Exception — Optional
int[] arr = new int[3];
System.out.println(arr[5]); // Runtime failure
✔ No compiler enforcement
✔ Better prevented using validations
Why Java Introduced Checked Exceptions
- Forces robust error handling
- Prevents silent failures
- Improves reliability of enterprise applications
- Encourages explicit recovery logic
Why Unchecked Exceptions Exist
- Avoid cluttering code with excessive try-catch
- Represent coding mistakes
- Improve code readability
- Fail fast during development
Best Practices (Real-World)
Use Checked Exceptions When:
- Error is recoverable
- Caller can take corrective action
- Dealing with external resources
Use Unchecked Exceptions When:
- Error indicates programming bug
- Recovery is not meaningful
- Precondition violations occur
Common Beginner Mistakes
- Catching Exception everywhere
- Ignoring checked exceptions using empty catch blocks
- Converting all exceptions to unchecked
- Using checked exceptions for programming errors
Interview-Ready Answers
Short Answer
Checked exceptions are verified by the compiler and must be handled, while unchecked exceptions occur at runtime and are not enforced by the compiler.
Detailed Answer
In Java, checked exceptions represent recoverable conditions and must be either handled or declared at compile time. Unchecked exceptions extend RuntimeException and usually indicate programming errors. Java uses this distinction to balance safety and flexibility.
Key Takeaway
Checked exceptions enforce responsibility. Unchecked exceptions enforce correctness. Using the right exception type leads to cleaner APIs, safer code, and better maintainability.
Examples: Checked vs Unchecked Exceptions
1. Checked Exception – Compile-Time Error
import java.io.FileInputStream;
class Demo {
public static void main(String[] args) {
// FileInputStream fis = new FileInputStream("data.txt"); // ❌ compile-time error
}
}
Explanation
- FileNotFoundException is checked
- Must be handled or declared
2. Handling Checked Exception with try-catch
import java.io.FileInputStream;
class Demo {
public static void main(String[] args) {
try {
new FileInputStream("data.txt");
} catch (Exception e) {
System.out.println("Checked exception handled");
}
}
}
Output
Checked exception handled
3. Handling Checked Exception with throws
import java.io.FileInputStream;
import java.io.FileNotFoundException;
class Demo {
static void read() throws FileNotFoundException {
new FileInputStream("data.txt");
}
public static void main(String[] args) throws FileNotFoundException {
read();
}
}
Explanation
- Responsibility passed to caller
4. Unchecked Exception – No Compile-Time Error
class Demo {
public static void main(String[] args) {
int a = 10 / 0;
}
}
Explanation
- ArithmeticException is unchecked
- Detected only at runtime
5. Catching Unchecked Exception
class Demo {
public static void main(String[] args) {
try {
int a = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Unchecked exception handled");
}
}
}
Output
Unchecked exception handled
6. Checked Exception in Method Signature
import java.io.IOException;
class Demo {
static void read() throws IOException {}
public static void main(String[] args) throws IOException {
read();
}
}
Explanation
- Checked exceptions must be declared or handled
7. Unchecked Exception – No throws Needed
class Demo {
static void calc() {
int[] a = new int[2];
a[5] = 10;
}
public static void main(String[] args) {
calc();
}
}
Explanation
- ArrayIndexOutOfBoundsException is unchecked
8. Exception Propagation – Checked Exception
import java.io.IOException;
class Demo {
static void m1() throws IOException {
m2();
}
static void m2() throws IOException {
throw new IOException("IO error");
}
public static void main(String[] args) {
try {
m1();
} catch (IOException e) {
System.out.println("Handled in main");
}
}
}
Output
Handled in main
9. Exception Propagation – Unchecked Exception
class Demo {
static void m1() {
m2();
}
static void m2() {
throw new NullPointerException();
}
public static void main(String[] args) {
try {
m1();
} catch (Exception e) {
System.out.println("Unchecked handled");
}
}
}
Output
Unchecked handled
10. Overriding Method – Checked Exception Rule
import java.io.IOException;
class A {
void show() throws IOException {}
}
class B extends A {
// void show() throws Exception {} // ❌ not allowed
}
Explanation
- Cannot throw broader checked exception while overriding
11. Overriding Method – Removing Checked Exception
import java.io.IOException;
class A {
void show() throws IOException {}
}
class B extends A {
void show() {} // allowed
}
Explanation
- Child can remove checked exception
12. Overriding Method – Unchecked Exception Allowed
class A {
void show() {}
}
class B extends A {
void show() throws RuntimeException {}
}
Explanation
- Unchecked exceptions have no restriction
13. Custom Checked Exception
class InvalidUserException extends Exception {
InvalidUserException(String msg) {
super(msg);
}
}
class Demo {
static void login(String user) throws InvalidUserException {
if (!user.equals("admin")) {
throw new InvalidUserException("Invalid user");
}
}
public static void main(String[] args) throws InvalidUserException {
login("guest");
}
}
14. Custom Unchecked Exception
class InvalidAmountException extends RuntimeException {
InvalidAmountException(String msg) {
super(msg);
}
}
class Demo {
static void pay(int amt) {
if (amt <= 0) {
throw new InvalidAmountException("Amount invalid");
}
}
public static void main(String[] args) {
pay(-10);
}
}
15. throw with Checked Exception
import java.io.IOException;
class Demo {
static void test() throws IOException {
throw new IOException("IO issue");
}
public static void main(String[] args) throws IOException {
test();
}
}
Explanation
- Checked exception must be declared
16. throw with Unchecked Exception
class Demo {
static void test() {
throw new NullPointerException("Null issue");
}
public static void main(String[] args) {
test();
}
}
Explanation
- No throws needed
17. Checked Exception in Constructor
import java.io.IOException;
class Demo {
Demo() throws IOException {
throw new IOException("Error");
}
public static void main(String[] args) throws IOException {
new Demo();
}
}
18. Unchecked Exception in Constructor
class Demo {
Demo() {
throw new ArithmeticException();
}
public static void main(String[] args) {
new Demo();
}
}
19. Common Interview Trap
class Demo {
static void test() {
try {
throw new Exception();
} catch (Exception e) {
throw new RuntimeException();
}
}
public static void main(String[] args) {
test();
}
}
Explanation
- Checked exception converted to unchecked
20. Interview Summary – Checked vs Unchecked
class Demo {
static void checked() throws Exception {}
static void unchecked() {}
public static void main(String[] args) throws Exception {
checked();
unchecked();
}
}
Key Differences
- Checked → compile-time check, must handle or declare
- Unchecked → runtime only, no enforcement
- Checked → IOException, SQLException
- Unchecked → NullPointerException, ArithmeticException