ZeroToSky
Java Tutorial 75 of 143
Basics
  • Introduction
  • Download and Install Java
  • Download and Install IntelliJ IDEA, Eclipse
  • Creating First Java Application in IntelliJ IDEA
  • JDK vs JRE vs JVM
  • Print output
  • Taking Input
  • Identifiers
  • Keywords
  • Variables
  • Data Types
  • Literals
  • Wrapper Classes
  • Operators
  • Decision Making
  • Loops and Jump Statements
  • Project: Number Guessing Game

All 17 lessons →

Methods
  • Introduction
  • Static Methods vs Instance Methods
  • Access Modifiers
  • Command Line Arguments
  • Variable Arguments (Varargs)

All 5 lessons →

Arrays
  • Introduction
  • One Dimensional Arrays
  • Multidimensional Arrays
  • Array Class
  • Arrays Class

All 5 lessons →

Strings
  • Introduction
  • String
  • StringBuffer
  • StringBuilder
  • String Class Methods
  • StringJoiner
  • StringTokenizer

All 7 lessons →

OOP & Interface

All 14 lessons →

Collections
  • Collection class
  • Collection Interface
  • List Interface
  • ArrayList
  • LinkedList
  • Set Interface
  • HashSet
  • LinkedHashSet
  • TreeSet
  • Queue Interface
  • PriorityQueue
  • Deque
  • ArrayDeque
  • Map Interface in Java
  • HashMap
  • LinkedHashMap
  • TreeMap
  • Hashtable
  • Iterator
  • Comparable and Comparator

All 20 lessons →

Exception Handling

All 7 lessons →

Multithreading & Concurrency
  • Introduction
  • Thread Class
  • Runnable Interface
  • Thread Life Cycle
  • Thread Priority
  • Synchronization
  • Inter-Thread Communication
  • Executor Framework
  • Callable and Future
  • Concurrent Collections

All 10 lessons →

Java 8 Features
  • Lambda Expressions
  • Functional Interfaces
  • Method References
  • Stream API
  • Optional Class
  • Default and Static Methods in Interface
  • Date and Time API

All 7 lessons →

Advanced Java Concepts
  • File Handling
  • Serialization and Deserialization
  • Reflection API
  • Annotations
  • Garbage Collection
  • Memory Management
  • JVM Architecture
  • Class Loading
  • Networking
  • Regular Expressions

All 10 lessons →

JDBC
  • Introduction
  • JDBC Driver
  • JDBC Connection
  • Types of Statements in JDBC
  • Transactions
  • ResultSet
  • Metadata
  • Connection Pooling

All 8 lessons →

GUI & Desktop
  • AWT
  • Swing
  • JavaFX

All 3 lessons →

Web & Enterprise
  • Servlets
  • JSP
  • Spring Framework
  • Spring Boot
  • Hibernate
  • REST API Development

All 6 lessons →

Practice Projects
  • Project: Number Guessing Game
  • Project: Banking System
  • Project: Student Management System
  • Project: Library Management System
  • Project: Quiz Application

All 5 lessons →

Quiz and Coding Practice
  • Java Topic-wise Quiz
  • Coding Practice Problems
  • Java Basics Coding Practice Problems
  • Java Exercises

All 4 lessons →

Interview Questions
  • Core Java Interview Questions and Answers
  • Advanced Java Interview Questions and Answers
  • Java Interview Questions

All 3 lessons →

DSA & Competitive Programming
  • Arrays and Strings
  • Linked List
  • Stack
  • Queue
  • Tree
  • Graph
  • Heap
  • Hashing
  • Sorting
  • Searching
  • Dynamic Programming
  • Roadmap for DSA in Java

All 12 lessons →

Java Checked vs Unchecked Exceptions

Learn the difference between checked and unchecked exceptions in Java, including compiler checking, exception handling, examples, use cases, and best practices.

Gaurav 8 min read Sign in to save
On this page

Java Checked vs Unchecked Exceptions

Java exceptions are commonly divided into two categories: checked exceptions and unchecked exceptions.

The main difference is whether the Java compiler requires the exception to be caught or declared.

  • Checked exceptions are checked by the compiler and must generally be handled or declared.
  • Unchecked exceptions are not checked by the compiler and usually represent programming errors or invalid runtime conditions.

Understanding this distinction is important for Java exception handling, application design, and interviews.


What Is a Checked Exception?

A checked exception is an exception that the Java compiler requires you to handle or declare.

Checked exceptions generally extend Exception but do not extend RuntimeException.

Examples include:

IOException
SQLException
FileNotFoundException
ClassNotFoundException
InterruptedException

For example:

import java.io.IOException;

public class Main {

    static void readData() throws IOException {
        throw new IOException("Unable to read data");
    }

    public static void main(String[] args) {

        try {
            readData();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}

The compiler requires IOException to be handled or declared.


Why Are They Called Checked Exceptions?

They are called checked exceptions because the compiler checks whether the exception is handled or declared.

Consider:

import java.io.IOException;

public class Main {

    static void readData() {
        throw new IOException("Unable to read data");
    }
}

This produces a compilation error because IOException is a checked exception and the method neither catches nor declares it.

The method needs to declare it:

static void readData() throws IOException {
    throw new IOException("Unable to read data");
}

Or handle it:

static void readData() {

    try {
        throw new IOException("Unable to read data");
    } catch (IOException e) {
        System.out.println(e.getMessage());
    }
}

What Is an Unchecked Exception?

An unchecked exception is an exception that the Java compiler does not require you to catch or declare.

Unchecked exceptions generally extend RuntimeException.

Examples include:

NullPointerException
ArithmeticException
IllegalArgumentException
ArrayIndexOutOfBoundsException
NumberFormatException

For example:

public class Main {

    static void divide(int a, int b) {

        if (b == 0) {
            throw new ArithmeticException(
                "Cannot divide by zero"
            );
        }

        System.out.println(a / b);
    }

    public static void main(String[] args) {
        divide(10, 0);
    }
}

The method does not need to declare:

throws ArithmeticException

because ArithmeticException is unchecked.


Java Exception Hierarchy

Understanding the exception hierarchy makes the difference clearer.

Throwable
│
├── Error
│
└── Exception
    │
    ├── RuntimeException
    │   ├── NullPointerException
    │   ├── ArithmeticException
    │   ├── IllegalArgumentException
    │   └── IndexOutOfBoundsException
    │
    ├── IOException
    ├── SQLException
    ├── ClassNotFoundException
    └── InterruptedException

The important distinction is:

Exception
├── RuntimeException → Unchecked
└── Other Exception subclasses → Generally Checked

Error types are also not subject to the checked-exception requirement.


Checked vs Unchecked Exceptions

The main differences are shown below.

Feature Checked Exception Unchecked Exception
Checked by compiler Yes No
Must be caught or declared Yes No
Common base Exception RuntimeException
Occurs Often due to conditions outside normal program control Often due to programming errors or invalid runtime conditions
Example IOException NullPointerException
throws required Generally yes if not caught No
Custom exception base Exception RuntimeException

Example of a Checked Exception

Reading a file can result in an IOException.

import java.io.FileReader;
import java.io.IOException;

public class Main {

    static void readFile() throws IOException {

        FileReader reader = new FileReader("data.txt");

        reader.close();
    }

    public static void main(String[] args) {

        try {
            readFile();
        } catch (IOException e) {
            System.out.println(
                "Unable to read the file"
            );
        }
    }
}

The method declares:

throws IOException

because IOException is checked.


Example of an Unchecked Exception

Consider accessing an invalid array index:

public class Main {

    public static void main(String[] args) {

        int[] numbers = {10, 20, 30};

        System.out.println(numbers[5]);
    }
}

This results in:

ArrayIndexOutOfBoundsException

There is no requirement to write:

throws ArrayIndexOutOfBoundsException

because it is an unchecked exception.


Checked Exception Handling

There are two primary ways to deal with a checked exception.

1. Handle It with try-catch

try {
    readFile();
} catch (IOException e) {
    System.out.println(e.getMessage());
}

2. Declare It with throws

static void readFile() throws IOException {
    // file operation
}

The second approach passes responsibility to the caller.


Unchecked Exception Handling

Unchecked exceptions do not have to be caught or declared.

For example:

public class Main {

    static int divide(int a, int b) {
        return a / b;
    }

    public static void main(String[] args) {
        System.out.println(divide(10, 0));
    }
}

This can result in:

ArithmeticException

The compiler does not require:

try-catch

or:

throws ArithmeticException

However, you can still handle the exception if doing so is appropriate.

try {
    System.out.println(divide(10, 0));
} catch (ArithmeticException e) {
    System.out.println("Cannot divide by zero");
}

Why Does Java Have Checked Exceptions?

Checked exceptions are intended for conditions that a caller may reasonably be expected to handle.

For example, when reading a file:

readFile();

The file might:

  • Not exist
  • Be inaccessible
  • Become unavailable
  • Cause an I/O failure

The compiler forces the developer to acknowledge the possibility.

This can make certain failure paths explicit in the API.


Why Does Java Have Unchecked Exceptions?

Unchecked exceptions are commonly used for conditions that indicate invalid program state, invalid arguments, or programming mistakes.

For example:

String name = null;

System.out.println(name.length());

This produces:

NullPointerException

Similarly:

int[] values = {1, 2, 3};

System.out.println(values[10]);

produces an index-related runtime exception.

These conditions often indicate that the program needs to be corrected rather than that every caller should be forced to catch the exception.


Checked Exception Example with File Handling

Consider a file-reading operation.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Main {

    static void readFile() throws IOException {

        BufferedReader reader =
            new BufferedReader(
                new FileReader("data.txt")
            );

        String line = reader.readLine();

        System.out.println(line);

        reader.close();
    }

    public static void main(String[] args) {

        try {
            readFile();
        } catch (IOException e) {
            System.out.println(
                "File could not be read"
            );
        }
    }
}

IOException is checked, so the exception must be handled or declared.


Unchecked Exception Example with Input Validation

Consider a method that requires a positive number.

public class Calculator {

    static void calculate(int number) {

        if (number <= 0) {
            throw new IllegalArgumentException(
                "Number must be positive"
            );
        }

        System.out.println(
            "Number: " + number
        );
    }
}

IllegalArgumentException is unchecked.

The method does not need:

throws IllegalArgumentException

although Java allows you to declare unchecked exceptions if desired.


Custom Checked Exception

You can create a checked custom exception by extending Exception.

class InsufficientBalanceException
        extends Exception {

    public InsufficientBalanceException(String message) {
        super(message);
    }
}

Use it:

class BankAccount {

    private double balance = 5000;

    void withdraw(double amount)
            throws InsufficientBalanceException {

        if (amount > balance) {
            throw new InsufficientBalanceException(
                "Insufficient balance"
            );
        }

        balance -= amount;
    }
}

Because the custom exception extends Exception, it is checked.


Custom Unchecked Exception

You can create an unchecked custom exception by extending RuntimeException.

class InvalidProductException
        extends RuntimeException {

    public InvalidProductException(String message) {
        super(message);
    }
}

Use it:

class ProductService {

    static void validatePrice(double price) {

        if (price <= 0) {
            throw new InvalidProductException(
                "Price must be greater than zero"
            );
        }
    }
}

No throws declaration is required.


Checked vs Unchecked Custom Exceptions

The difference can be summarized with two classes.

Checked

class UserNotFoundException
        extends Exception {
}

Usage:

void findUser()
        throws UserNotFoundException {
}

The compiler requires handling or declaration.

Unchecked

class UserNotFoundException
        extends RuntimeException {
}

Usage:

void findUser() {
}

No compiler requirement exists to catch or declare it.


throw with Checked and Unchecked Exceptions

The throw keyword can be used with both types.

Checked

throw new IOException("File error");

Because IOException is checked, the surrounding method must handle or declare it.

Unchecked

throw new IllegalArgumentException(
    "Invalid argument"
);

No handling or declaration is required by the compiler.


throws with Checked and Unchecked Exceptions

throws can technically declare both checked and unchecked exceptions.

For example:

void process()
        throws IOException,
               IllegalArgumentException {
}

However, the compiler's checked-exception requirement applies to IOException, not IllegalArgumentException.

For unchecked exceptions, declaring them with throws can sometimes document the API, but it is not required.


Exception Propagation

Checked and unchecked exceptions can both propagate up the call stack.

For example:

static void method3() {
    throw new IllegalArgumentException("Invalid value");
}

static void method2() {
    method3();
}

static void method1() {
    method2();
}

The exception can propagate:

method3()
   ↓
method2()
   ↓
method1()
   ↓
main()

The difference is not whether an exception can propagate.

The key difference is the compiler requirement to handle or declare checked exceptions.


Checked Exceptions and Method Overriding

Checked exceptions have special rules when methods are overridden.

Suppose the parent class declares:

class Parent {

    void process() throws IOException {
    }
}

A child class can override the method without declaring the exception:

class Child extends Parent {

    @Override
    void process() {
    }
}

It can also declare the same checked exception:

class Child extends Parent {

    @Override
    void process() throws IOException {
    }
}

But an overriding method cannot introduce a broader new checked exception that is not permitted by the parent method's declaration.

For example, if the parent declares:

void process() throws IOException {
}

the child cannot override it with:

void process() throws Exception {
}

because Exception is broader than IOException.


Can an Unchecked Exception Be Declared?

Yes.

For example:

void process()
        throws IllegalArgumentException {
}

This is valid.

However, the compiler does not require callers to catch or declare IllegalArgumentException.

Compare:

void process()
        throws IOException {
}

with:

void process()
        throws IllegalArgumentException {
}

The first creates a checked-exception obligation for callers if it is not handled. The second does not.


Common Checked Exceptions

Some commonly encountered checked exceptions include:

Exception Typical Situation
IOException Input/output operation fails
FileNotFoundException File cannot be found or opened
SQLException Database-related operation fails
ClassNotFoundException Requested class cannot be found
InterruptedException A thread is interrupted while waiting or sleeping

These classes extend Exception without extending RuntimeException.


Common Unchecked Exceptions

Common unchecked exceptions include:

Exception Typical Situation
NullPointerException Using a null reference
ArithmeticException Invalid arithmetic operation
IllegalArgumentException Invalid method argument
NumberFormatException Invalid string-to-number conversion
ArrayIndexOutOfBoundsException Invalid array index
IndexOutOfBoundsException Invalid collection/string index
ClassCastException Invalid object type cast

These exceptions extend RuntimeException.


Common Mistakes

Mistake 1: Assuming Every Exception Must Be Caught

This is not true.

Unchecked exceptions do not have to be caught.

throw new IllegalArgumentException("Invalid value");

The compiler does not require a catch block.


Mistake 2: Assuming throws Is Required for Every Exception

It is not.

This is valid:

void validate(int value) {
    if (value < 0) {
        throw new IllegalArgumentException("Invalid value");
    }
}

IllegalArgumentException is unchecked.


Mistake 3: Catching Exception Everywhere

This can hide important problems:

try {
    process();
} catch (Exception e) {
    // ignore
}

Catching exceptions without appropriate handling can make debugging difficult.

Prefer handling specific exceptions where meaningful recovery is possible.


Mistake 4: Confusing Runtime with "Exception That Happens Later"

The term runtime exception refers specifically to exceptions derived from RuntimeException.

It does not simply mean any exception that occurs while the program is running.


When Should You Use Checked Exceptions?

Checked exceptions can be appropriate when:

  • The caller can reasonably recover from the condition.
  • The condition is part of the method's expected failure contract.
  • The caller needs to make an explicit decision about handling the failure.
  • The API benefits from communicating the checked failure path through the type system.

For example, file and I/O operations commonly involve checked exceptions.


When Should You Use Unchecked Exceptions?

Unchecked exceptions can be appropriate when:

  • The error represents invalid arguments.
  • A programming contract has been violated.
  • The caller cannot reasonably recover at that point.
  • The error indicates invalid application state.
  • Making every caller explicitly catch the exception would add little value.

For example:

if (amount < 0) {
    throw new IllegalArgumentException(
        "Amount cannot be negative"
    );
}

Important Design Consideration

The checked-versus-unchecked decision should be based on the API's intended error-handling contract rather than simply following a rule such as "always use checked exceptions" or "always use runtime exceptions."

For example, a custom business exception could be either:

class PaymentException extends Exception {
}

or:

class PaymentException extends RuntimeException {
}

The appropriate choice depends on whether callers are expected to explicitly handle the condition as part of the method's contract.


Quick Comparison

Aspect Checked Unchecked
Compiler checks handling Yes No
Base class Exception RuntimeException
Must catch or declare Yes No
Example IOException NullPointerException
Custom exception extends Exception extends RuntimeException
throw can be used Yes Yes
throws can be used Yes Yes
Common purpose Explicitly recoverable/declared failure conditions Invalid state, arguments, or programming errors

Interview Question: What Is the Main Difference?

Question

What is the difference between checked and unchecked exceptions in Java?

Answer

A checked exception is checked by the Java compiler. If a method can throw a checked exception and does not handle it internally, the method generally needs to declare it using throws.

Example:

void readFile() throws IOException {
}

An unchecked exception extends RuntimeException. The compiler does not require it to be caught or declared.

Example:

void validate(int age) {
    if (age < 18) {
        throw new IllegalArgumentException(
            "Invalid age"
        );
    }
}

The key difference is:

Checked Exception
→ Compiler requires handling or declaration

Unchecked Exception
→ Compiler does not require handling or declaration

Key Points to Remember

  • Checked exceptions are checked by the Java compiler.
  • Checked exceptions generally extend Exception without extending RuntimeException.
  • Checked exceptions must generally be caught or declared.
  • Unchecked exceptions extend RuntimeException.
  • Unchecked exceptions do not have to be caught or declared.
  • IOException is a common checked exception.
  • NullPointerException is a common unchecked exception.
  • Custom checked exceptions extend Exception.
  • Custom unchecked exceptions extend RuntimeException.
  • Both checked and unchecked exceptions can be thrown using throw.
  • Both can technically be declared using throws.
  • The key difference is the compiler's handling requirement.
  • The choice between checked and unchecked exceptions should consider the API's error-handling contract.

Conclusion

Java distinguishes exceptions based on whether the compiler requires them to be handled or declared.

Checked exceptions are subject to compile-time checking:

void readFile() throws IOException {
}

Unchecked exceptions are derived from RuntimeException and do not have the same compiler requirement:

void validate(int value) {
    if (value < 0) {
        throw new IllegalArgumentException(
            "Value cannot be negative"
        );
    }
}

Understanding checked and unchecked exceptions helps you design clearer exception-handling logic and make informed decisions when creating custom exceptions and Java APIs.

Related

Found a problem on this page, or something that could be clearer?

Goes straight to the author. Not published anywhere.