Understanding Checked and Unchecked Exceptions in Java
Course: Core Java Training
Topic: Understanding Checked and Unchecked Exceptions
Course Link: Core Java Training Course
Demo Link: Register for a Course Demo
Website: JustAcademy
1. Introduction to Exception Handling in Java
Exception handling is an important feature of Java that allows developers to manage errors and unexpected situations that occur during program execution. An exception is an event that interrupts the normal flow of a program. It may occur because of invalid input, missing files, network failures, incorrect calculations, or attempts to access unavailable resources.
Java provides an exception-handling mechanism that allows programs to detect exceptional conditions, handle recoverable problems, and release resources properly. Understanding checked and unchecked exceptions helps developers create reliable, maintainable, and secure applications.
Java classifies exceptions primarily according to whether the compiler requires them to be caught or declared. This distinction is the foundation of checked and unchecked exception handling.
Learning Objectives
- Understand the meaning of exceptions in Java.
- Learn the Java exception class hierarchy.
- Understand checked exceptions and their rules.
- Understand unchecked exceptions and their causes.
- Learn try, catch, finally, throw, and throws.
- Compare checked and unchecked exceptions with examples.
- Learn how to create custom exceptions.
- Apply exception-handling best practices in real-world applications.
2. What Is an Exception in Java?
An exception is an object representing an abnormal condition that occurs while a program is running. When an operation fails, Java may create or throw an exception object. The exception can then be handled by an appropriate catch block or propagated to the calling method.
For example, attempting to divide an integer by zero causes an ArithmeticException. Trying to read a file that does not exist may cause a FileNotFoundException.
Example: An Exception Occurring During Execution
public class ExceptionExample {
public static void main(String[] args) {
int a = 10;
int b = 0;
int result = a / b;
System.out.println(result);
}
}
Output
Exception in thread "main" java.lang.ArithmeticException: / by zero
Explanation: Java cannot perform integer division by zero. The JVM throws an ArithmeticException, and the program terminates because the exception is not handled.
2.1 Why Is Exception Handling Important?
- Prevents unexpected failures from going unaddressed.
- Allows programs to respond to recoverable errors.
- Separates error-handling logic from normal business logic.
- Helps developers provide meaningful error messages.
- Supports reliable resource management.
- Makes debugging and maintenance easier.
3. Java Exception Hierarchy
Java's exception hierarchy begins with the Throwable class. Throwable has two principal branches: Error and Exception.
Object
|
+-- Throwable
|
+-- Error
| +-- OutOfMemoryError
| +-- StackOverflowError
|
+-- Exception
|
+-- RuntimeException
| +-- ArithmeticException
| +-- NullPointerException
| +-- ArrayIndexOutOfBoundsException
| +-- IllegalArgumentException
|
+-- Other Exceptions
+-- IOException
+-- SQLException
+-- ClassNotFoundException
+-- InterruptedException
3.1 Throwable
Throwable is the superclass of objects that can be thrown and caught by Java's exception-handling mechanism. Its two main branches are Error and Exception.
3.2 Error
An Error generally represents a serious problem associated with the JVM or runtime environment, such as resource exhaustion or stack overflow. Applications typically should not attempt to recover from every Error because many indicate conditions the application cannot safely resolve.
3.3 Exception
The Exception class represents conditions that applications may need to handle. Exceptions are commonly divided into checked exceptions and unchecked exceptions.
3.4 RuntimeException
RuntimeException is a subclass of Exception. RuntimeException and its subclasses are unchecked, meaning Java does not require methods to catch or declare them.
4. Understanding Checked Exceptions
Checked exceptions are exceptions that the Java compiler checks at compile time. If a method can throw a checked exception, the calling code must generally either handle it using a suitable try-catch block or declare that it may propagate the exception using the throws keyword.
Checked exceptions are commonly associated with operations that may fail for reasons outside the immediate control of the program, such as file access, database operations, or thread interruption.
4.1 Characteristics of Checked Exceptions
- Checked by the compiler.
- Must be caught or declared when required by the language rules.
- Often represent recoverable or externally caused failures.
- Can be handled using try-catch.
- Can be propagated using throws.
- Most subclasses of Exception that are not subclasses of RuntimeException are checked exceptions.
4.2 Common Checked Exceptions
| Exception |
Description |
Example Situation |
IOException |
Represents input/output failures. |
Reading or writing a file fails. |
FileNotFoundException |
A file cannot be found or opened. |
Opening a missing file. |
SQLException |
Represents database access errors. |
A database query fails. |
ClassNotFoundException |
A requested class cannot be located during certain class-loading operations. |
Loading a class by name fails. |
InterruptedException |
Indicates that a thread was interrupted while waiting or sleeping. |
A sleeping thread is interrupted. |
ParseException |
Represents parsing failures in APIs that use this exception. |
A date string does not match the expected format. |
5. Example of a Checked Exception Using File Handling
Reading a file with Java's traditional file-reading APIs may result in checked exceptions. The compiler requires the code to handle or declare these exceptions.
Example Program
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CheckedExceptionExample {
public static void main(String[] args) {
try (BufferedReader reader =
new BufferedReader(new FileReader("data.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("Unable to read the file.");
System.out.println("Reason: " + e.getMessage());
}
}
}
Explanation
- The program attempts to open the file named
data.txt.
- The
FileReader and readLine() operations may throw IOException or its subclass FileNotFoundException.
- The try block contains the file-reading logic.
- The catch block handles an IOException if the operation fails.
- The try-with-resources statement automatically closes the reader when execution leaves the statement.
Note: If the file does not exist, the catch block handles the resulting file-opening failure. If the file exists and can be read, its contents are printed line by line.
6. Handling Checked Exceptions with throws
The throws keyword declares exceptions that a method may propagate to its caller. It does not handle the exception itself. The calling method must handle the checked exception or declare it when required.
Example Program
import java.io.FileReader;
import java.io.IOException;
public class ThrowsExample {
static void openFile() throws IOException {
FileReader reader = new FileReader("data.txt");
try {
System.out.println("File opened successfully.");
} finally {
reader.close();
}
}
public static void main(String[] args) {
try {
openFile();
} catch (IOException e) {
System.out.println("File operation failed: "
+ e.getMessage());
}
}
}
Explanation
- The
openFile() method declares throws IOException.
- The method does not catch the opening exception itself.
- The caller handles IOException inside a try-catch block.
- The finally block attempts to close the file reader after it has been opened.
In production code, prefer try-with-resources for closing resources automatically. The example uses finally to illustrate the relationship between throws and caller-side handling.
7. Understanding Unchecked Exceptions
Unchecked exceptions are exceptions that the compiler does not require programmers to catch or declare. They commonly occur because of programming mistakes, invalid assumptions, or improper handling of values.
Unchecked exceptions are subclasses of RuntimeException. The compiler allows a program to compile even if these exceptions are not explicitly handled.
7.1 Characteristics of Unchecked Exceptions
- Not subject to the compiler's catch-or-declare requirement.
- Commonly indicate programming errors or invalid operations.
- Can occur during program execution.
- May be handled with try-catch when recovery is appropriate.
- Often can be prevented through validation, correct logic, and testing.
7.2 Common Unchecked Exceptions
| Exception |
Description |
Example |
ArithmeticException |
An invalid arithmetic operation occurs. |
Integer division by zero. |
NullPointerException |
A null reference is used where an object is required. |
Calling a method on null. |
ArrayIndexOutOfBoundsException |
An array is accessed with an invalid index. |
Accessing index 5 in a three-element array. |
StringIndexOutOfBoundsException |
A string is accessed with an invalid index. |
Requesting a character beyond the string's bounds. |
NumberFormatException |
A string cannot be converted to a numeric value by the requested parsing method. |
Parsing "abc" as an integer. |
IllegalArgumentException |
A method receives an inappropriate argument. |
Passing an invalid configuration value. |
ClassCastException |
An invalid reference conversion is attempted at runtime. |
Casting an object to an incompatible type. |
8. Example of an Unchecked Exception
The following program demonstrates a NullPointerException, which occurs when code attempts to call a method on a null reference.
Example Program
public class UncheckedExceptionExample {
public static void main(String[] args) {
String name = null;
System.out.println(name.length());
}
}
Output
Exception in thread "main" java.lang.NullPointerException
Explanation
- The variable
name refers to no String object because its value is null.
- The program attempts to call the
length() method.
- Java throws a NullPointerException at runtime.
- The compiler does not require a catch block or throws declaration for this exception.
8.1 Preventing NullPointerException
public class NullCheckExample {
public static void main(String[] args) {
String name = null;
if (name != null) {
System.out.println(name.length());
} else {
System.out.println("Name is not available.");
}
}
}
Output
Name is not available.
Checking whether a reference is null before using it can prevent this particular failure. Better application design may also use validation, clear object contracts, and appropriate use of Optional where suitable.
9. Difference Between Checked and Unchecked Exceptions
| Feature |
Checked Exceptions |
Unchecked Exceptions |
| Compiler checking |
Compiler enforces catch-or-declare rules. |
No catch-or-declare requirement. |
| Class hierarchy |
Generally Exception subclasses other than RuntimeException subclasses. |
RuntimeException and its subclasses. |
| Typical causes |
External conditions and operations that may fail. |
Programming mistakes or invalid operations. |
| Handling requirement |
Must be caught or declared where required. |
Handling is optional from the compiler's perspective. |
| Examples |
IOException, SQLException, InterruptedException. |
NullPointerException, ArithmeticException, NumberFormatException. |
| Prevention |
Validate external conditions and handle expected failures. |
Validate inputs, correct logic, and test edge cases. |
| Propagation |
Can propagate through methods using throws. |
Can propagate without declaring throws. |
10. The try-catch Block
The try block contains code that may throw an exception. A corresponding catch block handles an exception of the specified type when it occurs.
Syntax
try {
// Code that may throw an exception
} catch (ExceptionType e) {
// Handle the exception
}
Example
public class TryCatchExample {
public static void main(String[] args) {
try {
int result = 10 / 0;
System.out.println(result);
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero.");
}
System.out.println("Program continues.");
}
}
Output
Cannot divide by zero.
Program continues.
The exception is caught, so execution continues after the try-catch statement.
11. Using Multiple Catch Blocks
A single try block may be followed by multiple catch blocks to handle different exception types separately. More specific exception types should appear before broader types, otherwise the broader catch block may make later catches unreachable.
public class MultipleCatchExample {
public static void main(String[] args) {
try {
String value = "abc";
int number = Integer.parseInt(value);
System.out.println(100 / number);
} catch (NumberFormatException e) {
System.out.println("Invalid numeric input.");
} catch (ArithmeticException e) {
System.out.println("Division by zero.");
}
}
}
Output
Invalid numeric input.
The string "abc" cannot be parsed as an integer, so NumberFormatException is caught before the division statement is reached.
12. Understanding the finally Block
The finally block is used for cleanup code that should normally run whether an exception occurs or not. It is commonly used to release resources or perform cleanup. For modern resource handling, try-with-resources is usually preferred for objects that implement AutoCloseable.
public class FinallyExample {
public static void main(String[] args) {
try {
int result = 10 / 2;
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Arithmetic error occurred.");
} finally {
System.out.println("Cleanup section executed.");
}
}
}
Output
Result: 5
Cleanup section executed.
Important: A finally block normally executes when control leaves the try-catch structure, but it is not absolutely guaranteed under circumstances such as abrupt JVM termination. Avoid using return statements inside finally because they can obscure results and exceptions.
13. Understanding throw and throws
The throw and throws keywords serve different purposes in Java exception handling.
| Feature |
throw |
throws |
| Purpose |
Explicitly throws an exception object. |
Declares exceptions a method or constructor may propagate. |
| Location |
Inside a method or block. |
In a method or constructor declaration. |
| Followed by |
An exception object. |
One or more exception class names. |
| Example |
throw new IllegalArgumentException("Invalid age"); |
void read() throws IOException |
Example Using throw
public class ThrowExample {
static void checkAge(int age) {
if (age < 18) {
throw new IllegalArgumentException(
"Age must be at least 18."
);
}
System.out.println("Access granted.");
}
public static void main(String[] args) {
checkAge(16);
}
}
The method explicitly throws an IllegalArgumentException when the supplied age is below 18. Since this is an unchecked exception, the compiler does not require the method to declare it.
14. Creating Custom Exceptions
Java allows developers to create custom exception classes to represent application-specific error conditions. A custom checked exception typically extends Exception. A custom unchecked exception typically extends RuntimeException.
14.1 Custom Checked Exception
class InsufficientBalanceException extends Exception {
public InsufficientBalanceException(String message) {
super(message);
}
}
public class BankAccount {
static void withdraw(double balance, double amount)
throws InsufficientBalanceException {
if (amount > balance) {
throw new InsufficientBalanceException(
"Insufficient account balance."
);
}
System.out.println("Withdrawal successful.");
}
public static void main(String[] args) {
try {
withdraw(1000, 1500);
} catch (InsufficientBalanceException e) {
System.out.println(e.getMessage());
}
}
}
Output
Insufficient account balance.
Explanation
- The custom exception extends Exception, making it checked.
- The withdraw() method declares the exception using throws.
- The method throws the exception when the requested amount exceeds the balance.
- The calling code catches the exception and displays the message.
14.2 Custom Unchecked Exception
class InvalidProductPriceException extends RuntimeException {
public InvalidProductPriceException(String message) {
super(message);
}
}
public class ProductExample {
static void validatePrice(double price) {
if (price < 0) {
throw new InvalidProductPriceException(
"Product price cannot be negative."
);
}
System.out.println("Price accepted.");
}
public static void main(String[] args) {
validatePrice(-100);
}
}
This custom exception extends RuntimeException, so the compiler does not require callers to catch or declare it.
15. Exception Handling Best Practices
- Catch exceptions only when you can handle them meaningfully or add useful context.
- Catch specific exception types instead of catching Exception indiscriminately.
- Do not silently ignore exceptions with empty catch blocks.
- Use descriptive error messages that help diagnose problems.
- Use try-with-resources for files, streams, and other AutoCloseable resources.
- Validate user input before performing operations.
- Use checked exceptions when callers can reasonably recover and the API contract benefits from requiring explicit handling.
- Use unchecked exceptions for programming errors and invalid arguments when appropriate.
- Preserve the original exception as a cause when wrapping it in another exception.
- Avoid exposing passwords, tokens, personal data, or other sensitive information in error messages and logs.
- Do not use exceptions as a replacement for ordinary control flow.
- When catching InterruptedException, normally restore the interrupt status with
Thread.currentThread().interrupt() if you cannot propagate the exception.
16. Common Mistakes to Avoid
16.1 Catching the Wrong Exception
A catch block only handles exceptions compatible with its declared type. Identify the exception that the operation can actually throw and handle it appropriately.
16.2 Using a Broad Catch Block Without a Reason
Catching Exception may conceal unrelated failures. Prefer specific exception types when you know which conditions you can handle.
16.3 Confusing Compile-Time Errors with Checked Exceptions
A checked exception is not necessarily a compile-time error. Java code can compile successfully when checked exceptions are properly caught or declared. The compiler reports an error when the required handling or declaration is missing.
16.4 Assuming Every Exception Is Recoverable
Some failures require the operation to stop or the application to report an error. Handle an exception only when the application can respond safely and meaningfully.
16.5 Ignoring Resource Cleanup
Files, streams, and database resources should be closed properly. Prefer try-with-resources when supported rather than relying on manual cleanup.
17. Practice Exercises
- Write a program that catches an ArithmeticException caused by integer division by zero.
- Read a file using FileReader and handle IOException.
- Write a method that declares IOException using the throws keyword.
- Convert a string to an integer and handle NumberFormatException.
- Create a program that checks a String reference before calling length().
- Write a method that throws IllegalArgumentException when a number is negative.
- Create a custom checked exception for an invalid bank withdrawal.
- Create a custom unchecked exception for invalid product information.
- Use multiple catch blocks to handle different exception types.
- Use try-with-resources to read a file and ensure the resource is closed.
18. Mini Project: Bank Account Exception Handling
Objective: Create a basic bank account program that demonstrates exception handling for invalid transactions.
Requirements
- Maintain an account balance.
- Allow deposits and withdrawals.
- Reject negative deposit amounts.
- Reject withdrawals that exceed the available balance.
- Create a custom exception for insufficient funds.
- Display appropriate messages for successful and unsuccessful transactions.
Suggested Implementation Steps
- Create a BankAccount class with a balance field.
- Implement deposit() and withdraw() methods.
- Validate transaction amounts before changing the balance.
- Create an InsufficientBalanceException class.
- Throw the custom exception when a withdrawal cannot be completed.
- Handle the exception in the main method.
- Test valid deposits, negative amounts, successful withdrawals, and insufficient-funds scenarios.
19. Interview Questions and Answers
Q1. What is an exception in Java?
Answer: An exception is an event represented by an object that disrupts the normal flow of program execution and may be handled or propagated.
Q2. What are checked exceptions?
Answer: Checked exceptions are exceptions that the compiler requires a method to catch or declare when the language's exception-handling rules apply. IOException and SQLException are common examples.
Q3. What are unchecked exceptions?
Answer: Unchecked exceptions are RuntimeException subclasses that do not have a compiler-enforced catch-or-declare requirement. Examples include NullPointerException and IllegalArgumentException.
Q4. What is the main difference between checked and unchecked exceptions?
Answer: Checked exceptions require handling or declaration where applicable, whereas unchecked exceptions do not require explicit handling or declaration.
Q5. What is the difference between throw and throws?
Answer: throw explicitly throws an exception object, while throws declares exceptions that a method or constructor may propagate.
Q6. Can unchecked exceptions be handled?
Answer: Yes. Unchecked exceptions can be caught with try-catch blocks when appropriate, even though the compiler does not require it.
Q7. What is the purpose of finally?
Answer: The finally block is intended for cleanup code that normally runs when control leaves the try-catch structure.
Q8. Can we create custom exceptions?
Answer: Yes. Extend Exception for a custom checked exception or RuntimeException for a custom unchecked exception.
Q9. Is NullPointerException checked or unchecked?
Answer: NullPointerException is unchecked because it extends RuntimeException.
Q10. Is IOException checked or unchecked?
Answer: IOException is a checked exception. It must be caught or declared when required.
Q11. What happens if a checked exception is not caught or declared?
Answer: The compiler reports an error when the code violates the checked-exception handling rules.
Q12. What is try-with-resources?
Answer: Try-with-resources automatically closes resources that implement AutoCloseable when the try statement completes.
Q13. What is the difference between Exception and Error?
Answer: Exception represents conditions applications may handle, while Error generally represents serious JVM or runtime problems that applications typically cannot safely recover from.
Q14. Why should exceptions not be ignored?
Answer: Ignoring exceptions can hide failures, produce incorrect results, and make debugging more difficult.
20. Quick Revision Notes
- Exception: An event that interrupts normal program execution.
- Throwable: The superclass of objects that can be thrown.
- Checked exception: Subject to compiler-enforced handling or declaration rules.
- Unchecked exception: RuntimeException or one of its subclasses.
- try: Contains code that may throw an exception.
- catch: Handles a matching exception.
- finally: Provides a place for cleanup code.
- throw: Explicitly throws an exception object.
- throws: Declares possible exception propagation.
- Custom exception: Represents application-specific failure conditions.
- try-with-resources: Automatically closes supported resources.
- Best practice: Handle exceptions specifically and preserve useful diagnostic information.
21. Conclusion
Checked and unchecked exceptions are essential concepts in Java exception handling. Checked exceptions help the compiler enforce explicit handling or declaration for certain failures, while unchecked exceptions commonly represent programming mistakes and invalid operations that can occur at runtime.
By understanding the exception hierarchy, using try-catch-finally correctly, applying throw and throws appropriately, and designing custom exceptions, developers can build more robust and maintainable Java applications.
Regular practice with file handling, input validation, custom exceptions, and resource management will strengthen your understanding of exception handling in Core Java.
Recommended Learning Resources
Explore the Core Java Training Course to learn more about Java programming, exception handling, object-oriented programming, and the Collections Framework.
To learn more about the training, visit Register for a Course Demo.
Visit the JustAcademy website for additional learning resources.