Topic 85 of 119 8. Exception Handling in Java Interactive Tutorial

Checked vs Unchecked Exceptions in Java: Compile-Time vs Runtime Errors

9 mins read Last updated: 22 Aug 2026 29,705 views

Direct Answer & Core Concept

Java exceptions are commonly divided into two important categories: checked exceptions and unchecked exceptions. Understanding the difference is essential for writing reliable Java applications and choosing the right exception-handling strategy.

Checked exceptions are verified by the Java compiler and generally require the programmer to handle or declare them. Unchecked exceptions are not checked by the compiler and usually represent programming errors, invalid state, or invalid input discovered while the program is running.

Detailed Explanation & Mechanics

What Are Checked Exceptions in Java?

A checked exception is an exception that the Java compiler requires the program to account for.

If a method can produce a checked exception, the exception generally must be:

  • handled with try-catch, or

  • declared using throws.

Common checked exceptions include:

Main.java
Run Online
IOExceptionSQLExceptionFileNotFoundExceptionClassNotFoundExceptionInterruptedException

For example:

Main.java
Run Online
import java.io.IOException;
public void readFile() throws IOException {
    // File operation
}

The throws declaration tells the caller that the method may propagate IOException.


What Are Unchecked Exceptions?

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

Unchecked exceptions are generally subclasses of RuntimeException.

Common examples include:

Main.java
Run Online
NullPointerExceptionArithmeticExceptionArrayIndexOutOfBoundsExceptionIllegalArgumentExceptionNumberFormatException

For example:

Main.java
Run Online
public void calculate() {
    int result = 10 / 0;
}

This code can produce:

The compiler does not require:

Main.java
Run Online
throws ArithmeticException

or a try-catch block.


Checked vs Unchecked Exceptions at a Glance

FeatureChecked ExceptionUnchecked Exception
Checked by compilerYesNo
Usually extendsExceptionRuntimeException
Catch or declare requiredGenerally yesNo
Often representsRecoverable/external conditionsProgramming errors or invalid state
ExampleIOExceptionNullPointerException
throws requiredFor unhandled checked exceptionsNot required
DetectedCompile time requirementUsually during execution

A useful rule is:

Checked = compiler requires handling or declaration

Unchecked = compiler does not require handling or declaration


Java Exception Hierarchy

To understand the difference, first look at the basic hierarchy:

Architecture Diagram
                    Throwable
                       |
          ┌────────────┴────────────┐
          |                         |
       Error                    Exception
                                    |
                         ┌──────────┴──────────┐
                         |                     |
                RuntimeException          Other
                         |               Checked
                         |
                   Unchecked

Examples:

Architecture Diagram
Throwable
├── Error
│   └── OutOfMemoryError
│
└── Exception
    ├── IOException
    ├── SQLException
    ├── ClassNotFoundException
    │
    └── RuntimeException
        ├── NullPointerException
        ├── ArithmeticException
        ├── IllegalArgumentException
        └── NumberFormatException

The key distinction is whether the exception is a subclass of RuntimeException.


Why Are Checked Exceptions Called "Checked"?

They are called checked exceptions because the compiler checks whether your code has dealt with them according to Java's exception rules.

Consider:

Main.java
Run Online
import java.io.FileReader;
public void openFile() {
    FileReader reader = new FileReader("data.txt");
}

This can cause FileNotFoundException.

Because it is a checked exception, the compiler requires you to handle or declare it.

For example:

Main.java
Run Online
public void openFile() throws Exception {
    FileReader reader = new FileReader("data.txt");
}

Or:

Main.java
Run Online
public void openFile() {
    try {
        FileReader reader = new FileReader("data.txt");
    } catch (Exception e) {
        System.out.println("File could not be opened.");
    }
}

Checked Exception Example

Consider reading a file:

Main.java
Run Online
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public String readFile() throws IOException {
    try(BufferedReader reader = new BufferedReader( new FileReader("data.txt"))) {
        return reader.readLine();
    }
}

IOException is checked.

If you do not catch it, the method needs to declare it:

The caller then has to handle or further declare the exception.


Handling a Checked Exception

Instead of declaring the exception, you can handle it:

Main.java
Run Online
public void readData() {
    try {
        readFile();
    } catch (IOException e) {
        System.out.println( "Unable to read the file.");
    }
}

This satisfies the compiler because the checked exception is handled.


Declaring a Checked Exception

Another option is to use throws:

Main.java
Run Online
public void readData() throws IOException {
    readFile();
}

Now the current method does not handle the exception.

It passes responsibility to its caller.

This is called exception propagation.


What Happens if You Ignore a Checked Exception?

Suppose you write:

Main.java
Run Online
public void readData() {
    readFile();
}

If readFile() declares:

the compiler reports an error because IOException is checked.

The code cannot be compiled until you either catch the exception or declare it.

This is one of the main differences between checked and unchecked exceptions.


Unchecked Exception Example

Consider:

Main.java
Run Online
public void divide(int a, int b) {
    int result = a / b;
    System.out.println(result);
}

If b is zero:

the program can produce:

The compiler does not force you to write:

Main.java
Run Online
throws ArithmeticException

You can handle it if appropriate, but it is not required by the compiler.


NullPointerException Example

Another common unchecked exception is NullPointerException.

Main.java
Run Online
String name = null;
System.out.println(name.length());

At runtime, this can result in:

The compiler does not require a try-catch.

The better solution is often to prevent the invalid state rather than simply catch the exception.

For example:

Main.java
Run Online
if (name != null) {
    System.out.println(name.length());
}

ArrayIndexOutOfBoundsException

Consider:

Main.java
Run Online
int[] numbers = {
    10, 20, 30
};
System.out.println(numbers[5]);

The array has indexes:

Trying to access index 5 produces an ArrayIndexOutOfBoundsException at runtime.

The compiler does not require you to catch it.

A better approach is usually to correct the index logic or validate the index before accessing the array.


NumberFormatException

NumberFormatException is another unchecked exception.

Main.java
Run Online
String value = "abc";
int number = Integer.parseInt(value);

The string cannot be converted to an integer, so Java can throw:

You can handle it:

Main.java
Run Online
try {
    int number = Integer.parseInt(value);
} catch (NumberFormatException e) {
    System.out.println( "Please enter a valid number.");
}

However, you are not required to catch it simply because it is an unchecked exception.


Compile-Time Error vs Runtime Exception

The phrase compile-time vs runtime errors can be confusing.

A checked exception is not itself a "compile-time exception." Instead, the compiler enforces the catch-or-declare rule for checked exceptions.

For example:

Main.java
Run Online
public void readFile() {
    FileReader reader = new FileReader("data.txt");
}

The compiler rejects the code because the checked exception is not handled or declared.

By contrast:

Main.java
Run Online
public void calculate() {
    int result = 10 / 0;
}

The code can compile, but an ArithmeticException can occur when that statement executes.

So a more accurate comparison is:

Main.java
Run Online
Checked exception→ compiler enforces handling/declarationUnchecked exception→ compiler does not enforce handling/declaration→ failure may occur during execution

Compile-Time Errors Are Not the Same as Checked Exceptions

This distinction is important.

A syntax error is a true compile-time error:

Main.java
Run Online
public void test() {
    System.out.println("Hello"
}

The Java compiler cannot compile the program.

A checked exception is different.

For example:

Main.java
Run Online
FileReader reader = new FileReader("data.txt");

The compiler rejects the code because the checked exception contract has not been satisfied.

The exception itself would occur during execution if the file operation actually fails.

So:

Checked exception ≠ compile-time exception

The compiler simply enforces how checked exceptions must be handled or declared.


Main Difference Between Checked and Unchecked Exceptions

The most important difference is compiler enforcement.

Checked

Main.java
Run Online
public void load() throws IOException {
    // Operation
}

The compiler requires the checked exception to be handled or declared.

Unchecked

Main.java
Run Online
public void calculate() {
    int result = 10 / 0;
}

The compiler does not require ArithmeticException to be declared or caught.


Common Checked Exceptions

Here are some frequently encountered checked exceptions:

IOException

Used for many input/output failures.

SQLException

Used by JDBC operations for database-related failures.

ClassNotFoundException

Can occur when Java cannot locate a requested class.

Main.java
Run Online
throws ClassNotFoundException

InterruptedException

Can occur when a thread is interrupted while waiting or sleeping.

Main.java
Run Online
throws InterruptedException

FileNotFoundException

A more specific I/O exception associated with opening files.

Main.java
Run Online
throws FileNotFoundException

Common Unchecked Exceptions

NullPointerException

Occurs when code attempts to use a null reference in an invalid way.

Main.java
Run Online
String text = null;
text.length();

ArithmeticException

Can occur during invalid arithmetic operations.

ArrayIndexOutOfBoundsException

Occurs when an array is accessed with an invalid index.

Main.java
Run Online
int[] values = {
    1, 2, 3
};
System.out.println(values[5]);

IllegalArgumentException

Indicates that a method received an inappropriate argument.

Main.java
Run Online
throw new IllegalArgumentException( "Age cannot be negative");

NumberFormatException

Occurs when a string cannot be converted into the expected numeric format.


Custom Checked Exceptions

You can create your own checked exception by extending Exception.

Main.java
Run Online
class InsufficientBalanceException extends Exception {
    public InsufficientBalanceException( String message) {
        super(message);
    }
}

Then:

Main.java
Run Online
public void withdraw(double amount) throws InsufficientBalanceException {
    if (amount > balance) {
        throw new InsufficientBalanceException( "Insufficient balance");
    }
}

Because the exception extends Exception and not RuntimeException, it is checked.


Custom Unchecked Exceptions

To create an unchecked exception, extend RuntimeException.

Main.java
Run Online
class InvalidCouponException extends RuntimeException {
    public InvalidCouponException( String message) {
        super(message);
    }
}

You can then write:

Main.java
Run Online
public void applyCoupon(String coupon) {
    if (coupon == null || coupon.isBlank()) {
        throw new InvalidCouponException( "Coupon code is invalid");
    }
}

No throws declaration is required.


Checked Exception Flow

A checked exception usually follows this pattern:

Architecture Diagram
Method performs operation
↓
Checked exception possible
↓
Compiler requires handling
↓
┌───────────────┴───────────────┐
↓

↓
try-catch                       throws
↓

↓
Handle locally             Pass to caller

This explicit handling requirement is one reason checked exceptions can make failure contracts visible in method signatures.


Unchecked Exception Flow

Unchecked exceptions work differently:

Main.java
Run Online
Method performs operation↓Invalid state/input/programming error↓Runtime exception occurs↓Exception can propagate↓Caller may catch it if appropriate

The compiler does not require the catch-or-declare pattern.


throw With Checked Exceptions

A checked exception can be explicitly thrown:

Main.java
Run Online
public void validateAge(int age) throws InvalidAgeException {
    if (age < 18) {
        throw new InvalidAgeException( "Age must be at least 18");
    }
}

There are two important parts:

Main.java
Run Online
throw↓Actually throws the exception object

and:

Main.java
Run Online
throws↓Declares the checked exception

throw With Unchecked Exceptions

Unchecked exceptions can also be explicitly thrown:

Main.java
Run Online
public void validateAge(int age) {
    if (age < 0) {
        throw new IllegalArgumentException( "Age cannot be negative");
    }
}

There is no need to write:

Main.java
Run Online
throws IllegalArgumentException

The exception can still propagate normally if it is not caught.


When Should You Use Checked Exceptions?

Checked exceptions can be useful when the caller can reasonably be expected to take action in response to a failure.

Examples include:

  • A file may not exist.

  • A network operation may fail.

  • A database operation may fail.

  • An external resource may be unavailable.

  • A thread may be interrupted.

For example:

Main.java
Run Online
public String readConfig() throws IOException {
    // Read configuration
}

The caller can decide whether to retry, use a fallback, report an error, or propagate the failure.


When Should You Use Unchecked Exceptions?

Unchecked exceptions are commonly used for conditions such as:

  • Invalid method arguments.

  • Violated object state.

  • Programming mistakes.

  • Invalid assumptions.

  • Errors that callers are not expected to recover from directly.

For example:

Main.java
Run Online
public void setAge(int age) {
    if (age < 0) {
        throw new IllegalArgumentException( "Age cannot be negative");
    }
}

The caller does not have a compiler-enforced requirement to catch the exception.


Checked Exceptions and API Design

When designing a public Java API, choosing checked versus unchecked exceptions affects how developers interact with your methods.

For example:

Main.java
Run Online
public void loadFile() throws IOException {
}

The exception is visible in the method signature.

A caller understands that file-related failure is part of the method's declared contract.

With an unchecked exception:

Main.java
Run Online
public void validateOrder() {
}

The method does not force callers to handle its runtime exceptions.

This can make APIs less verbose, but important failure conditions may become less explicit.


Advantages of Checked Exceptions

Explicit failure contract

The method signature communicates possible checked failures.

Compiler assistance

The compiler can identify code that has not handled or declared a checked exception.

Clear caller responsibility

The caller must make an explicit decision about handling or propagating the exception.

Useful for external failures

They can be appropriate for operations involving files, databases, networks, and other external resources.


Disadvantages of Checked Exceptions

Checked exceptions can also have costs.

More verbose code

Methods may need many try-catch blocks or throws declarations.

Propagation through multiple layers

A checked exception may need to be declared across several layers of an application.

API rigidity

Changing the checked exceptions exposed by an API can affect callers.

Poor use can create boilerplate

If every method simply propagates generic checked exceptions, the code can become difficult to maintain.

Therefore, checked exceptions should be used deliberately.


Advantages of Unchecked Exceptions

Less boilerplate

Callers do not need to catch or declare every runtime exception.

Flexible APIs

Method signatures can remain simpler.

Good for programming errors

Invalid state and programming mistakes can naturally use runtime exceptions.

Useful for validation

Exceptions such as IllegalArgumentException are commonly used when method arguments violate a method's contract.


Disadvantages of Unchecked Exceptions

Failure contract may be less visible

A method signature does not require the caller to handle the exception.

Errors can appear at runtime

The compiler does not force the programmer to account for them.

Poor handling can hide bugs

If runtime exceptions are ignored or broadly caught, defects can become harder to identify.


Checked vs Unchecked: Real-World Example

Consider an application that loads a user profile.

A database operation might produce a checked exception:

Main.java
Run Online
public User loadUser(int id) throws SQLException {
    // Database operation
}

But an invalid method argument might produce an unchecked exception:

Main.java
Run Online
public User loadUser(int id) {
    if (id <= 0) {
        throw new IllegalArgumentException( "User ID must be positive");
    } // Load user
}

The two failures have different characteristics:

Main.java
Run Online
Database failure→ external operation→ SQLExceptionInvalid ID→ caller violated method contract→ IllegalArgumentException

Important: Errors Are Different From Exceptions

Java also has Error.

For example:

Main.java
Run Online
OutOfMemoryErrorStackOverflowError

These are not ordinary exceptions intended for normal application recovery.

The simplified hierarchy is:

Architecture Diagram
Throwable
├── Error
└── Exception
    ├── RuntimeException
    └── Other checked exceptions

Do not treat Error as simply another category of application exception.


Common Mistakes

Mistake 1: Calling Checked Exceptions "Compile-Time Exceptions"

A checked exception is not an exception that happens at compile time.

The compiler simply enforces handling or declaration rules.


Mistake 2: Catching Every Runtime Exception

Avoid:

Main.java
Run Online
try {
    process();
} catch (RuntimeException e) {
    // Ignore
}

This can hide programming defects.

Handle exceptions where you can make a meaningful decision.


Mistake 3: Using throws Exception Everywhere

This:

Main.java
Run Online
public void process() throws Exception {
}

can make an API less descriptive.

Prefer meaningful exception types when practical.


Mistake 4: Using Checked Exceptions for Every Validation

Not every validation failure needs a checked exception.

For example:

Main.java
Run Online
throw new IllegalArgumentException( "Age must be positive");

may be more appropriate than creating a checked exception for every argument validation rule.


Mistake 5: Catching an Exception Without Taking Action

Avoid:

Main.java
Run Online
catch (IOException e) {
}

An empty catch block can silently hide an important failure.


Best Practices

1. Understand the exception's meaning

Choose the exception category based on the failure and the API contract.

2. Use specific exception types

Prefer:

over:

when possible.

3. Do not catch exceptions unnecessarily

Catch an exception when the current layer can actually handle or translate it meaningfully.

4. Avoid swallowing exceptions

Do not silently ignore failures.

5. Preserve causes when wrapping exceptions

Main.java
Run Online
throw new ApplicationException( "Operation failed", e);

6. Do not use Error for normal business failures

Use appropriate exception types for expected application conditions.

7. Prevent runtime exceptions where practical

Validate input and maintain valid object state rather than relying on runtime exceptions as normal control flow.


Frequently Asked Questions

What is the difference between checked and unchecked exceptions?

Checked exceptions are subject to compiler-enforced catch-or-declare rules. Unchecked exceptions are not.

Is NullPointerException checked or unchecked?

NullPointerException is unchecked because it extends RuntimeException.

Is IOException checked or unchecked?

IOException is a checked exception.

Do unchecked exceptions need throws?

No. Java does not require unchecked exceptions to be declared with throws.

Do checked exceptions always need try-catch?

No. They can either be caught or declared with throws.

Is a checked exception a compile-time error?

No. The exception occurs during runtime. The compiler checks whether the code handles or declares it correctly.

Can I create a custom checked exception?

Yes. Extend Exception.

Main.java
Run Online
class MyException extends Exception {
}

Can I create a custom unchecked exception?

Yes. Extend RuntimeException.

Main.java
Run Online
class MyException extends RuntimeException {
}

Which is better: checked or unchecked exceptions?

Neither is universally better. The appropriate choice depends on the API contract, failure type, recoverability, and application design.

Can unchecked exceptions be caught?

Yes. For example:

Main.java
Run Online
try {
    int value = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("Cannot divide by zero.");
}

The difference is that catching them is not compiler-required.

Quick Revision

Architecture Diagram
                    Java Exceptions
                          |
             ┌────────────┴────────────┐
↓

↓
Checked                  Unchecked
             |                         |
       Compiler checks             No compiler
       handling/declaration        catch/declare rule
             |                         |
       IOException              NullPointerException
       SQLException             ArithmeticException
       InterruptedException    IllegalArgumentException

Checked exception

Main.java
Run Online
public void readFile() throws IOException {
}

Unchecked exception

Main.java
Run Online
public void validate(int age) {
    if (age < 0) {
        throw new IllegalArgumentException( "Invalid age");
    }
}

Remember

Checked exceptions are compiler-enforced handling/declaration requirements.

Unchecked exceptions are runtime exceptions that Java does not require you to catch or declare.

Graphics and Design Ideas

Graphic 1: Checked vs Unchecked

Architecture Diagram
              Java Exceptions
                    |
          ┌─────────┴─────────┐
↓

↓
CHECKED             UNCHECKED
↓

↓
Compiler requires       Compiler does not
 catch or declare        require catch/declare
↓

↓
IOException             NullPointerException
 SQLException             ArithmeticException

Graphic 2: Exception Hierarchy

Architecture Diagram
                 Throwable
                     |
          ┌──────────┴──────────┐
↓

↓
Error                Exception
                                |
                     ┌──────────┴──────────┐
↓

↓
RuntimeException          Checked
↓
Unchecked

Graphic 3: Compiler Flow

Architecture Diagram
        Checked Exception
↓
Compiler detects
↓
┌───────┴───────┐
↓

↓
try-catch        throws
↓

↓
Handle           Caller

Graphic 4: Real-World Comparison

Main.java
Run Online
File missing↓IOException↓Checked↓Caller must handle/declareInvalid method argument↓IllegalArgumentException↓Unchecked↓Compiler does not require catch/declare

Graphic 5: One-Page Cheat Sheet

Create a compact comparison card with:

CheckedUnchecked
Compiler-enforced handling/declarationNo compiler-enforced handling/declaration
Often external/recoverable conditionsOften programming errors/invalid state
IOExceptionNullPointerException
SQLExceptionIllegalArgumentException
InterruptedExceptionArithmeticException
throws often appearsthrows not required

Runnable Code Example: Checked vs Unchecked Exceptions in Java

Java 17+
Main.java
Run Online
public class CheckedVsUncheckedDemo {
    // Unchecked: Compiler doesn't force try-catch
    public static void divide(int a, int b) {
        if (b == 0) throw new ArithmeticException("Division by zero");
        System.out.println("Result: " +(a / b));
    } public static void main(String[] args) {
        divide(10, 2);
        System.out.println("Unchecked exceptions run without mandatory try-catch blocks.");
    }
}

Common Java Technical Interview Questions & Answers

Interview Prep
Q1

Why are RuntimeExceptions called unchecked exceptions?

Because the Java compiler does not check during compilation whether the calling code handles or declares them.
Q2

What is the downside of checked exceptions in large systems?

They pollute method signatures across layers and result in empty catch blocks or catch-and-ignore anti-patterns.

Key Takeaways, Best Practices & Clean Code Rules

Java Best Practice & Production Rules

Prefer unchecked exceptions for modern Java microservice architectures to keep API interfaces clean and modular.