Exception Handling in Java
Learn how Java handles runtime errors using try, catch, finally, throw, throws, custom exceptions, and best practices.
What is an Exception?
An exception is an event that interrupts the normal flow of a Java program during execution.
Exception handling allows a program to detect exceptional situations and respond to them without unnecessarily terminating the application.
try
↓
Risky Code
↓
Exception?
↓
catch
↓
Handle Exception
↓
finally
try-catch
The try block contains code that may throw an
exception. The catch block handles the exception.
try {
int result = 10 / 0;
}
catch (ArithmeticException exception) {
System.out.println(
"Cannot divide by zero"
);
}
finally
The finally block is commonly used for cleanup
operations. It normally executes after the try/catch processing,
including when an exception occurs.
try {
System.out.println(
"Opening resource"
);
}
catch (Exception exception) {
System.out.println(
"Exception occurred"
);
}
finally {
System.out.println(
"Cleanup completed"
);
}
Multiple catch Blocks
A single try block can be followed by multiple catch blocks when different exception types require different handling.
try {
int[] numbers = {10, 20, 30};
System.out.println(
numbers[5]
);
}
catch (ArrayIndexOutOfBoundsException exception) {
System.out.println(
"Invalid array index"
);
}
catch (Exception exception) {
System.out.println(
"Unexpected error"
);
}
Exception.
Exception Hierarchy
Throwable
├── Error
│ ├── OutOfMemoryError
│ └── StackOverflowError
│
└── Exception
├── RuntimeException
│ ├── NullPointerException
│ ├── ArithmeticException
│ └── IllegalArgumentException
│
└── Other Checked Exceptions
├── IOException
└── SQLException
Error generally represents serious conditions
that applications are not normally expected to recover from,
while Exception represents conditions that
application code may handle.
Checked Exceptions
Checked exceptions are exceptions that the compiler requires the program to handle or declare.
import java.io.IOException;
void readFile()
throws IOException {
// File operations
}
Examples include IOException and many other
exceptions derived from Exception but not from
RuntimeException.
Unchecked Exceptions
Unchecked exceptions are runtime exceptions. The compiler does not require them to be explicitly caught or declared.
int number = 10;
int result = number / 0;
This produces an ArithmeticException at runtime.
throw Keyword
The throw keyword is used to explicitly throw an
exception.
int age = 15;
if (age < 18) {
throw new IllegalArgumentException(
"Age must be at least 18"
);
}
throws Keyword
The throws keyword declares that a method may
propagate one or more exceptions to its caller.
import java.io.IOException;
void loadData()
throws IOException {
// File operation
}
throw actually throws an exception,
while throws declares possible exceptions.
Custom Exception
Applications can define their own exception classes to represent domain-specific error conditions.
class InvalidAgeException
extends Exception {
public InvalidAgeException(
String message
) {
super(message);
}
}
Using a Custom Exception
static void validateAge(int age)
throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException(
"Age must be 18 or above"
);
}
System.out.println(
"Eligible"
);
}
Multi-Catch
Java allows multiple exception types to be handled by a single
catch block using the | operator.
try {
// risky operation
}
catch (
IOException | IllegalArgumentException exception
) {
System.out.println(
"Operation failed"
);
}
Try-with-Resources
Try-with-resources automatically closes objects that implement
AutoCloseable.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
try (
BufferedReader reader =
new BufferedReader(
new FileReader("data.txt")
)
) {
String line = reader.readLine();
System.out.println(line);
}
catch (IOException exception) {
System.out.println(
"Unable to read file"
);
}
Exception Chaining
Exception chaining preserves the original cause when a higher-level exception is created.
try {
loadData();
}
catch (IOException exception) {
throw new RuntimeException(
"Unable to load application data",
exception
);
}
The original exception is retained as the cause and can be
inspected using methods such as getCause().
Useful Exception Methods
| Method | Purpose |
|---|---|
getMessage() |
Returns the exception message. |
getCause() |
Returns the underlying cause. |
printStackTrace() |
Prints diagnostic stack-trace information. |
toString() |
Returns a string representation of the exception. |
Stack Trace
A stack trace shows the sequence of method calls that led to the exception.
try {
int result = 10 / 0;
}
catch (ArithmeticException exception) {
exception.printStackTrace();
}
Exception Handling Best Practices
- Catch exceptions at the level where meaningful recovery or handling is possible.
-
Prefer specific exception types instead of catching
Exceptioneverywhere. - Do not silently ignore exceptions.
- Use meaningful exception messages.
- Preserve the original cause when wrapping exceptions.
- Use try-with-resources for closeable resources.
- Avoid using exceptions as normal program-flow control.
Common Mistakes
- Catching a very broad exception without a good reason.
- Empty catch blocks.
- Losing the original cause when rethrowing an exception.
- Using exceptions to replace ordinary conditional logic.
Interview Questions
throw is used to explicitly throw an
exception, while throws declares that
a method can propagate specified exceptions.
finally block is commonly used for
cleanup code that should execute after exception
handling.
AutoCloseable.
Summary
Java exception handling uses try, catch, finally, throw, and throws to manage exceptional conditions. Important concepts include checked and unchecked exceptions, custom exceptions, multi-catch, try-with-resources, exception chaining, and good exception-handling practices.