IOExceptionSQLExceptionFileNotFoundExceptionClassNotFoundExceptionInterruptedExceptionChecked vs Unchecked Exceptions in Java: Compile-Time vs Runtime Errors
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, ordeclared using
throws.
Common checked exceptions include:
For example:
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:
NullPointerExceptionArithmeticExceptionArrayIndexOutOfBoundsExceptionIllegalArgumentExceptionNumberFormatExceptionFor example:
public void calculate() {
int result = 10 / 0;
}This code can produce:
ArithmeticExceptionThe compiler does not require:
throws ArithmeticExceptionor a try-catch block.
Checked vs Unchecked Exceptions at a Glance
| Feature | Checked Exception | Unchecked Exception |
|---|---|---|
| Checked by compiler | Yes | No |
| Usually extends | Exception | RuntimeException |
| Catch or declare required | Generally yes | No |
| Often represents | Recoverable/external conditions | Programming errors or invalid state |
| Example | IOException | NullPointerException |
throws required | For unhandled checked exceptions | Not required |
| Detected | Compile time requirement | Usually 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:
Throwable
|
┌────────────┴────────────┐
| |
Error Exception
|
┌──────────┴──────────┐
| |
RuntimeException Other
| Checked
|
UncheckedExamples:
Throwable
├── Error
│ └── OutOfMemoryError
│
└── Exception
├── IOException
├── SQLException
├── ClassNotFoundException
│
└── RuntimeException
├── NullPointerException
├── ArithmeticException
├── IllegalArgumentException
└── NumberFormatExceptionThe 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:
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:
public void openFile() throws Exception {
FileReader reader = new FileReader("data.txt");
}Or:
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:
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:
throws IOExceptionThe caller then has to handle or further declare the exception.
Handling a Checked Exception
Instead of declaring the exception, you can handle it:
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:
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:
public void readData() {
readFile();
}If readFile() declares:
throws IOExceptionthe 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:
public void divide(int a, int b) {
int result = a / b;
System.out.println(result);
}If b is zero:
divide(10, 0);the program can produce:
ArithmeticExceptionThe compiler does not force you to write:
throws ArithmeticExceptionYou can handle it if appropriate, but it is not required by the compiler.
NullPointerException Example
Another common unchecked exception is NullPointerException.
String name = null;
System.out.println(name.length());At runtime, this can result in:
NullPointerExceptionThe 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:
if (name != null) {
System.out.println(name.length());
}ArrayIndexOutOfBoundsException
Consider:
int[] numbers = {
10, 20, 30
};
System.out.println(numbers[5]);The array has indexes:
012Trying 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.
String value = "abc";
int number = Integer.parseInt(value);The string cannot be converted to an integer, so Java can throw:
NumberFormatExceptionYou can handle it:
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:
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:
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:
Checked exception→ compiler enforces handling/declarationUnchecked exception→ compiler does not enforce handling/declaration→ failure may occur during executionCompile-Time Errors Are Not the Same as Checked Exceptions
This distinction is important.
A syntax error is a true compile-time error:
public void test() {
System.out.println("Hello"
}The Java compiler cannot compile the program.
A checked exception is different.
For example:
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
public void load() throws IOException {
// Operation
}The compiler requires the checked exception to be handled or declared.
Unchecked
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.
throws IOExceptionSQLException
Used by JDBC operations for database-related failures.
throws SQLExceptionClassNotFoundException
Can occur when Java cannot locate a requested class.
throws ClassNotFoundExceptionInterruptedException
Can occur when a thread is interrupted while waiting or sleeping.
throws InterruptedExceptionFileNotFoundException
A more specific I/O exception associated with opening files.
throws FileNotFoundExceptionCommon Unchecked Exceptions
NullPointerException
Occurs when code attempts to use a null reference in an invalid way.
String text = null;
text.length();ArithmeticException
Can occur during invalid arithmetic operations.
int result = 10 / 0;ArrayIndexOutOfBoundsException
Occurs when an array is accessed with an invalid index.
int[] values = {
1, 2, 3
};
System.out.println(values[5]);IllegalArgumentException
Indicates that a method received an inappropriate argument.
throw new IllegalArgumentException( "Age cannot be negative");NumberFormatException
Occurs when a string cannot be converted into the expected numeric format.
Integer.parseInt("abc");Custom Checked Exceptions
You can create your own checked exception by extending Exception.
class InsufficientBalanceException extends Exception {
public InsufficientBalanceException( String message) {
super(message);
}
}Then:
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.
class InvalidCouponException extends RuntimeException {
public InvalidCouponException( String message) {
super(message);
}
}You can then write:
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:
Method performs operation
↓
Checked exception possible
↓
Compiler requires handling
↓
┌───────────────┴───────────────┐
↓
↓
try-catch throws
↓
↓
Handle locally Pass to callerThis explicit handling requirement is one reason checked exceptions can make failure contracts visible in method signatures.
Unchecked Exception Flow
Unchecked exceptions work differently:
Method performs operation↓Invalid state/input/programming error↓Runtime exception occurs↓Exception can propagate↓Caller may catch it if appropriateThe compiler does not require the catch-or-declare pattern.
throw With Checked Exceptions
A checked exception can be explicitly thrown:
public void validateAge(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException( "Age must be at least 18");
}
}There are two important parts:
throw↓Actually throws the exception objectand:
throws↓Declares the checked exceptionthrow With Unchecked Exceptions
Unchecked exceptions can also be explicitly thrown:
public void validateAge(int age) {
if (age < 0) {
throw new IllegalArgumentException( "Age cannot be negative");
}
}There is no need to write:
throws IllegalArgumentExceptionThe 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:
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:
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:
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:
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:
public User loadUser(int id) throws SQLException {
// Database operation
}But an invalid method argument might produce an unchecked exception:
public User loadUser(int id) {
if (id <= 0) {
throw new IllegalArgumentException( "User ID must be positive");
} // Load user
}The two failures have different characteristics:
Database failure→ external operation→ SQLExceptionInvalid ID→ caller violated method contract→ IllegalArgumentExceptionImportant: Errors Are Different From Exceptions
Java also has Error.
For example:
OutOfMemoryErrorStackOverflowErrorThese are not ordinary exceptions intended for normal application recovery.
The simplified hierarchy is:
Throwable
├── Error
└── Exception
├── RuntimeException
└── Other checked exceptionsDo 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:
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:
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:
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:
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:
throws IOExceptionover:
throws Exceptionwhen 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
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.
class MyException extends Exception {
}Can I create a custom unchecked exception?
Yes. Extend RuntimeException.
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:
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
Java Exceptions
|
┌────────────┴────────────┐
↓
↓
Checked Unchecked
| |
Compiler checks No compiler
handling/declaration catch/declare rule
| |
IOException NullPointerException
SQLException ArithmeticException
InterruptedException IllegalArgumentExceptionChecked exception
public void readFile() throws IOException {
}Unchecked exception
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
Java Exceptions
|
┌─────────┴─────────┐
↓
↓
CHECKED UNCHECKED
↓
↓
Compiler requires Compiler does not
catch or declare require catch/declare
↓
↓
IOException NullPointerException
SQLException ArithmeticExceptionGraphic 2: Exception Hierarchy
Throwable
|
┌──────────┴──────────┐
↓
↓
Error Exception
|
┌──────────┴──────────┐
↓
↓
RuntimeException Checked
↓
UncheckedGraphic 3: Compiler Flow
Checked Exception
↓
Compiler detects
↓
┌───────┴───────┐
↓
↓
try-catch throws
↓
↓
Handle CallerGraphic 4: Real-World Comparison
File missing↓IOException↓Checked↓Caller must handle/declareInvalid method argument↓IllegalArgumentException↓Unchecked↓Compiler does not require catch/declareGraphic 5: One-Page Cheat Sheet
Create a compact comparison card with:
| Checked | Unchecked |
|---|---|
| Compiler-enforced handling/declaration | No compiler-enforced handling/declaration |
| Often external/recoverable conditions | Often programming errors/invalid state |
IOException | NullPointerException |
SQLException | IllegalArgumentException |
InterruptedException | ArithmeticException |
throws often appears | throws not required |
Runnable Code Example: Checked vs Unchecked Exceptions in Java
Java 17+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.");
}
}