Table of contents
1.
Introduction
2.
What is Exception Handling in Java?
3.
Hierarchy of Java Exception Classes
4.
Types of Java Exceptions
4.1.
Checked Exceptions:
4.2.
Unchecked Exceptions: 
4.3.
Errors: 
5.
Exceptions in Java
5.1.
1. Checked Exceptions
5.2.
2. Unchecked Exceptions
6.
Errors in Java
6.1.
Common Errors in Java
7.
Keywords used in Exception Handling in Java
7.1.
throw – Raises an Exception
7.2.
throws – Reports Exception
7.3.
try – Monitors Exception
7.4.
catch – Handles the Exception
7.5.
finally – Executes After Try/Catch
8.
Difference Between Exception and Error in Java
9.
Comparison Table: Exception vs. Error
10.
Exceptions that can be handled using Exception Handling 
11.
Exception handling in Java involves three operations:
11.1.
1. Declaring Checked Exceptions
11.2.
2. Throwing an exception
11.3.
3. Catching an exception
11.3.1.
1. Via a call to method1() inside a try-catch or try-catch-finally as given below. 
11.3.2.
2. If method2(), which calls method1(), does not want to handle exceptions with a try-catch, it can specify these exceptions to be thrown up the call stack as follows.
12.
Using try-catch
13.
Multiple catch clauses
14.
Displaying a Description of an Exception
14.1.
Java
15.
Nested try statements
15.1.
Java
15.2.
Java
16.
Control flow in try-catch or try-catch-finally
16.1.
1. Exception occurs in the try block and handled in the catch block
16.2.
Java
16.3.
2. Exception occurred in try-block is not handled in catch block
16.4.
Java
16.5.
3. Exception doesn’t occur in try-block
16.6.
Java
17.
Using finally
18.
Advantages of Exception Handling in Java
19.
Frequently Asked Questions
19.1.
When to use try-catch?
19.2.
What are the five keywords used in java exception handling?
19.3.
How are the exceptions handled in Java? Specify one method.
19.4.
Which keyword is used to throw an exception?
19.5.
Can we throw an exception manually?
19.6.
Can we catch and throw the same exception in a program?
20.
Conclusion
Last Updated: Jun 26, 2025
Hard

Exception Handling in Java

Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Exception handling is a critical feature in Java that ensures the robustness and reliability of your applications. It provides a structured approach to managing runtime errors, allowing programs to respond gracefully to unexpected situations without crashing. By using Java's exception handling mechanisms, you can capture and address errors such as invalid input, network failures, and file operations issues, thereby enhancing user experience and maintaining system stability. In this blog, we will delve into the fundamentals of exception handling in Java, exploring key concepts such as try-catch blocks, throwing exceptions, and creating custom exceptions.

Exception Handling In Java Using Try-Catch And Finally

Must Read, Multithreading in java, Duck Number in Java

What is Exception Handling in Java?

Exception handling in Java is a mechanism that allows developers to manage runtime errors in a structured way. It involves using specific language constructs to catch exceptions, handle them, and ensure that the program can recover or exit gracefully. The primary constructs used in exception handling are try, catch, finally, and throw. By enclosing code that might generate exceptions in a try block and providing catch blocks to handle those exceptions, developers can prevent errors from causing program crashes and implement appropriate recovery strategies.

Hierarchy of Java Exception Classes

Java's exception handling framework is built around a class hierarchy that starts with the Throwable class. The hierarchy is structured as follows:

Here is a diagram showing the hierarchy of Java Exception classes:

java.lang.Object  
   └── java.lang.Throwable  
         ├── java.lang.Error  
         │     ├── AssertionError  
         │     ├── OutOfMemoryError  
         │     └── StackOverflowError  
         └── java.lang.Exception  
               ├── java.lang.RuntimeException  
               │     ├── NullPointerException  
               │     ├── ArithmeticException  
               │     ├── ArrayIndexOutOfBoundsException  
               │     └── IllegalArgumentException  
               └── (Checked Exceptions)  
                     ├── IOException  
                     │     └── FileNotFoundException  
                     ├── SQLException  
                     └── ClassNotFoundException
  • Throwable: The root class for all exceptions and errors.
    • Exception: Represents exceptions that a program might want to catch. It includes:
      • RuntimeException: Represents exceptions that occur during the program’s execution, which are unchecked and do not require explicit handling.
      • Checked Exceptions: Subclasses of Exception that are not subclasses of RuntimeException. They must be either caught or declared in the method signature using throws.
    • Error: Represents serious problems that a program typically should not try to handle, such as OutOfMemoryError and StackOverflowError.

Types of Java Exceptions

Java exceptions are categorized into several types:

Checked Exceptions:

These exceptions are checked at compile-time. The programmer must handle them using try-catch blocks or declare them using the throws keyword. Examples include IOException and SQLException.

Unchecked Exceptions

These exceptions are not checked at compile-time and include RuntimeException and its subclasses. They often represent programming errors, such as NullPointerException and ArrayIndexOutOfBoundsException.

Errors

These are serious issues that are not typically handled by programs. They include VirtualMachineError, OutOfMemoryError, and StackOverflowError. These usually indicate problems that are beyond the control of the program.

Exceptions in Java

Exceptions are divided into two categories:

1. Checked Exceptions

Checked exceptions are checked at compile-time, meaning the compiler ensures they are handled using try-catch blocks or declared using throws.

Example:

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

public class CheckedExceptionExample {
    public static void main(String[] args) {
        try {
            File file = new File("test.txt");
            FileReader fr = new FileReader(file);  // May throw IOException
        } catch (IOException e) {
            System.out.println("File not found: " + e.getMessage());
        }
    }
}
You can also try this code with Online Java Compiler
Run Code


Common checked exceptions: IOException, SQLException

2. Unchecked Exceptions

Unchecked exceptions occur at runtime and are usually caused by programming errors. They do not require explicit handling.

Example:

public class UncheckedExceptionExample {
    public static void main(String[] args) {
        int a = 10, b = 0;
        int result = a / b;  // Throws ArithmeticException
    }
}
You can also try this code with Online Java Compiler
Run Code


Common unchecked exceptions: NullPointerException, ArithmeticException

Errors in Java

Errors represent critical failures in the JVM or system resources. Unlike exceptions, errors cannot be handled or recovered from using try-catch blocks.

Common Errors in Java

OutOfMemoryError: Occurs when the JVM runs out of memory.

public class StackOverflowExample {
    public static void recursiveMethod() {
        recursiveMethod();  // Infinite recursion
    }
    public static void main(String[] args) {
        recursiveMethod();
    }
}
You can also try this code with Online Java Compiler
Run Code


StackOverflowError: Happens when a program has excessive recursive calls.

public class MemoryErrorExample {
    public static void main(String[] args) {
        int[] largeArray = new int[Integer.MAX_VALUE];  // Causes OutOfMemoryError
    }
}
You can also try this code with Online Java Compiler
Run Code

 

  • Exceptions are recoverable errors caused by faulty code and should be handled using try-catch.
     
  • Errors are serious system issues that cannot be recovered from.

Keywords used in Exception Handling in Java

The five main clauses in exception handling are:

throw – Raises an Exception

The throw keyword in Java is used to explicitly raise (or throw) an exception. It is typically used inside a method when a specific condition is encountered that should not be handled by the method itself. The throw statement is followed by an instance of Throwable (usually an exception object).
Example:

if (age < 18) {
    throw new IllegalArgumentException("Age must be 18 or above");
}

throws – Reports Exception

The throws keyword is used in a method signature to report one or more exceptions that the method might throw. This informs the caller of the method that it must handle or further declare the exception. It is mainly used with checked exceptions.
Example:

public void readFile(String filePath) throws IOException {
    FileReader reader = new FileReader(filePath);
}

try – Monitors Exception

The try block is used to wrap code that might throw an exception. It monitors the code and ensures that if an exception occurs, the control is transferred to the appropriate catch block. It is the starting point of exception handling in Java.
Example:

try {
    int result = 10 / 0;
}

catch – Handles the Exception

The catch block is used to handle the exception that occurs in the try block. Each catch block handles a specific type of exception. Multiple catch blocks can be used to handle different exception types separately.
Example:

try {
    int[] arr = new int[5];
    arr[10] = 50;
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("Array index is out of bounds!");
}

finally – Executes After Try/Catch

The finally block contains code that is guaranteed to execute after the try and catch blocks, regardless of whether an exception was thrown or not. It is commonly used for resource cleanup, such as closing files or releasing database connections.
Example:

try {
    FileInputStream fis = new FileInputStream("data.txt");
} catch (FileNotFoundException e) {
    System.out.println("File not found.");
} finally {
    System.out.println("Closing the file.");
}

Difference Between Exception and Error in Java

In Java, Exceptions and Errors are two types of Throwable objects that handle abnormal situations during program execution. Exceptions represent conditions a program can handle and recover from, while Errors indicate serious issues beyond a program’s control. Understanding their differences helps developers write robust and error-free applications by implementing proper exception handling mechanisms.

Comparison Table: Exception vs. Error

AspectExceptionError
DefinitionAn unexpected event that occurs during program execution and can be handled.A serious system-level issue that a program cannot recover from.
CauseCaused by faulty logic, incorrect input, or external issues.Caused by system failures, hardware malfunctions, or resource limitations.
ExamplesNullPointerException, IOExceptionOutOfMemoryError, StackOverflowError

Exceptions that can be handled using Exception Handling 

All exceptions descend from the Throwable parent class. But the hierarchy quickly divides into two branches: Error and Exception.

An essential element of Exception handling in Java is the Exception hierarchy. The Exception hierarchy is further divided into two branches:

  • Exceptions that are derived from RuntimeException
  • Exceptions that are not derived from RuntimeException

The general rule is: A RuntimeException happens because the programmer made a programming error. Any other exception occurs because some other thing, such as an I/O error, happened. The compiler checks for exceptional handlers for all the checked or compile-time exceptions. 

Inside the Java run-time system, the Error hierarchy defines internal errors and resource exhaust situations. A program should never throw this type of object. If an internal error occurs, a programmer has no choice but to warn the user and manually exit the program. These are highly uncommon circumstances.

Thus Exceptions are recoverable and can be handled by exception handling techniques, whereas Errors are irrecoverable and lead to abnormal termination of the program.

Also see,  Swap Function in Java

Exception handling in Java involves three operations:

1. Declaring Checked Exceptions

A Java method must declare the types of checked exceptions it may throw, using the keyword “throws” in its signature.

For example, consider the declaration of the below-given method. After the throws keyword, the name of the potential exceptions is mentioned that the program may encounter during execution.

public void TestThrows() throws Exception1, Exception2 {...}

2. Throwing an exception

A program can throw an exception if it encounters a situation it cannot handle using the keyword “throw”. In other words, When a Java program encounters an abnormal situation, the method having the incorrect code should create an appropriate exception object and throw it to the JVM using the below statement. 

public void TestThrow() throws Exception1, Exception2
{
// Exception1 occurs
   if ( ... ) throw new Exception1(...);   
// construct an Exception1 object and throw to JVM


   // Exception2 occurs
   if ( ... ) throw new Exception2(...);   
// construct an Exception2 object and throw to JVM
}

 

Note: The keyword to declare the exception in the method’s signature is “throws”. And the keyword to throw an exception object within the method’s body is “throw”.

3. Catching an exception

When a method throws an exception, the JVM looks for a matching exception handler in the call stack. Each exception handler is limited to one type of exception. An exception handler that can handle a given class can also handle its subclasses. The program ends if no exception handler is found in the call stack.

For example, suppose a method method1() declares that it may throw Exception1 and Exception2 in its signature, as follows:

public void method1() throws Exception1, Exception2 { ...... }

There are two ways in which we can use method1 in our program.

1. Via a call to method1() inside a try-catch or try-catch-finally as given below. 

public void method2() 
{  // no exception declared
   try
{
      // uses method1() which declares Exception1 & Exception2
      method1();
    } 
catch (Exception1 ex) {
      // Exception handler for Exception1
} 
catch (Exception2 ex} {
      // Exception handler for Exception2
} 
}

 

2. If method2(), which calls method1(), does not want to handle exceptions with a try-catch, it can specify these exceptions to be thrown up the call stack as follows.

public void method2() throws Exception1, Exception2 
{   
// for the higher-level method to handle


// uses method1() which declares "throws Exception1, Exception2"
   method1();   // no need for try-catch

}

Using try-catch

The first step in creating an exception handler is to use a try block to enclose any code that might throw an exception.

 A try block looks something like this in general:

try {
    code
}
catch and finally blocks

Multiple catch clauses

Exception handlers can be associated by placing one or more catch blocks after the try block. The code inside the catch block is executed when the exception handler is invoked.

try {


} catch (ExceptionType name) {


} catch (ExceptionType name) {


}

 

  • Each catch block is an exception handler that handles the type of exception indicated by its argument. 
     
  • The parameter must be the name of a class that inherits from the Throwable class and indicates the type of exception that the handler can handle. 
     
  • The exception can be referred to by name in the handler.
     
  • When the exception handler is the first in the call stack with an ExceptionType that matches the type of the exception raised, the runtime system calls it.
     

Example:

try {


} catch (IndexOutOfBoundsException e) 
{
    System.err.println("IndexOutOfBoundsException: " + e.getMessage());
} 
catch (IOException e) 
{
    System.err.println("Caught IOException: " + e.getMessage());
}

Displaying a Description of an Exception

To display the description of an exception, simply pass the exception as an argument to the print method.

The below-given program is an implementation of the above problem:

  • Java

Java

import java.io.*;

public class TestClass {
public static void main(String args[])
   {
       try {
           String a = "Coding Ninjas"; // length is 13
           char c = a.charAt(14); // accessing 14th element
           System.out.println(c);
       }
       catch (StringIndexOutOfBoundsException e) {
 System.out.println("Displaying the description of Exception:"+e);
       }
       System.out.println("Execution Completed!!");
   }
}
You can also try this code with Online Java Compiler
Run Code

Output

Displaying the description of Exception: java.lang.StringIndexOutOfBoundsException: String index out of range: 14
Execution Completed!!
You can also try this code with Online Java Compiler
Run Code

 

Note: Exception handlers are capable of much more than simply printing error messages or terminating the program. They can utilise chained exceptions to accomplish error recovery. They can prompt the user to decide or propagate the error up to a higher-level handler.

Nested try statements

A situation may occur in which a part of a block causes one error, and the complete block causes another error. Exception handlers must be nested in such cases. 

In the same manner, we can employ a try block within a try block in Java. The context of an exception is pushed into a stack each time a try statement is entered.

An example of nested try blocks is shown below.

Example1: To handle an ArithmeticException, an inner try block is used in this example. The outer try block then handles the ArrayIndexOutOfBoundsException.

  • Java

Java

import java.io.*;
class TestClass {
public static void main(String args[])
   {
       // Outer try block
       try {

          int a[] = { 1, 2, 3, 4, 5, 6, 7 };

           // printing element at index 7 i.e out
           System.out.println(a[7]);

           // inner try block
           try {

               // division by zero
               int x = a[2] / 0;
           }
           catch (ArithmeticException e2)
           {
               System.out.println("Arithmetic Exception encountered!!");
           }
       }
       catch (ArrayIndexOutOfBoundsException e1)
       {
           System.out.println("ArrayIndexOutOfBounds Exception encountered!!");
           System.out.println("Catch method of outer try block implemented!!");
       }
   }
}
You can also try this code with Online Java Compiler
Run Code


Output

ArrayIndexOutOfBounds Exception encountered!!
Catch method of outer try block implemented!!
  • If a try block does not have a catch block for a specific exception, the catch block of the parent block is searched for that exception, and if a match is found, the catch block of the parent is executed.
  • If none of the catch blocks catches the exception, the Java run-time system will handle it and display a system-generated message.

Example2: Another example of how the nested try block works can be seen here. Inside the body of the parent try block, you can see two try-catch blocks.

  • Java

Java

import java.io.*;
public class TestClass {
public static void main(String args[]){
//Parent try block
try{
//Child try block1
try{
System.out.println("Inside block1");
//Divide by zero exception........
int b =45/0;
}
catch(ArithmeticException e1){
System.out.println("Exception: e1");
}
//Child try block2
try{
System.out.println("Inside block2");
//Divide by zero exception again........
int b =45/0;
}
catch(ArrayIndexOutOfBoundsException e2){
System.out.println("Exception: e2");
}
}
catch(ArithmeticException e3){
System.out.println("Arithmetic Exception");
System.out.println("Inside parent's catch-1 block");
}
catch(ArrayIndexOutOfBoundsException e4){
System.out.println("ArrayIndexOutOfBoundsException");
System.out.println("Inside parent's catch-2 block");
}
catch(Exception e5){
System.out.println("Exception");
System.out.println("Inside parent's catch-3 block");
}
System.out.println("Ending the parent try-catch block.......");
}
}
You can also try this code with Online Java Compiler
Run Code

Output

Inside block1
Exception: e1
Inside block2
Arithmetic Exception
Inside parent's catch-1 block
Ending the parent try-catch block.......
  • Child try-catch block1:  Integer divide by zero caused an ArithmeticException since the catch of block1 is handling ArithmeticException “Exception: e1” displayed.
  • Child try-catch block2: ArithmeticException occurred again, but block 2’s catch only handles ArrayIndexOutOfBoundsException, so control jumps to the parent try-catch body and looks for the ArithmeticException catch handler in parent’s catch block. 
  • The message “Inside parent try block” appears because the catch of the parent’s try block handles this exception with a generic Exception handler that handles all exceptions.
  • Parent try Catch block: In this case, there was no exception. Hence the message “Ending the parent try-catch block…….” appeared.

Need more insights about the try Block, you can refer to the official java documentation here.

Control flow in try-catch or try-catch-finally

The flow control in all the various combinations of try, catch, and finally, blocks are explained below:

1. Exception occurs in the try block and handled in the catch block

  • If a statement in the try block throws an exception, the rest of the try block is skipped, and control is passed to the catch block. 
  • When the catch block is completed, the control will be transferred to the finally block if it is present in the code, and then the rest of the program will be executed.

Program:

  • Java

Java

import java.io.*;
public class TestClass
   {
public static void main (String[] args){
       int[] arr = new int[7];
       try
       {
           int i = arr[7];
           // this statement will not be executed
           // as exception is raised by above statement
           System.out.println("Inside try block");
       }
       catch(ArrayIndexOutOfBoundsException ex)
       {
           System.out.println("Inside catch block!!");
       }
       finally
       {
           System.out.println("Inside finally block!!");
       }
       // rest of the program will be executed
       System.out.println("Outside try-catch-finally clause");
   }
}
You can also try this code with Online Java Compiler
Run Code

Output

Inside catch block!!
Inside finally block!!
Outside try-catch-finally clause

2. Exception occurred in try-block is not handled in catch block

In certain circumstances, the default handler is called. If there is a final block, it will be executed first, followed by the default handler.

Program:

  • Java

Java

import java.io.*;
public class TestClass {
public static void main (String[] args)
   {
       int[] arr = new int[7];
       try
       {
           int i = arr[7];
           // this statement will not execute
           // as exception is raised by above statement
           System.out.println("Inside try block!!");
       }
       catch(NullPointerException ex)
       {
           System.out.println("Inside catch block!!");
       }
       
       finally
       {
           System.out.println("Inside finally block!!");
       }
       // rest of the program will not execute
       System.out.println("Outside try-catch-finally clause");
   }
}
You can also try this code with Online Java Compiler
Run Code

Output

Inside finally block!!
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 7
at TestClass.main(TestClass.java:8)

3. Exception doesn’t occur in try-block

In this situation, the catch block is never executed because it is only supposed to be executed when an exception occurs. If a final block exists, it will be executed before the rest of the program.

Program:

  • Java

Java

import java.io.*;
public class TestClass {
public static void main (String[] args)
   {
      try
      {
   String str = "123";
          int num = Integer.parseInt(str);
          // this statement will execute
       // as no any exception is raised by above statement
       System.out.println("End of the try block!!");
      }catch(NumberFormatException ex)
      {
       System.out.println("Inside catch block");
      }
      finally
      {
   System.out.println("Inside finally block!!");
      }
      System.out.println("Outside try-catch-finally clause");
   }
}
You can also try this code with Online Java Compiler
Run Code

Output

End of the try block!!
Inside finally block!!
Outside try-catch-finally clause

Using finally

When the try block exits, the finally block is always executed. Even if an unexpected exception occurs, the finally block is executed.

Important points regarding the finally block are given below:

  • The finally block is a crucial technique for reducing resource leaks.
  • While closing a file or recovering resources, we must place the code in a finally block to ensure the resource is always recovered.
  • In these cases, consider utilizing the try-with-resources statement, which automatically releases system resources when they are no longer required.

Refer to this code snippet from java documentation explaining the above utility:

static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        br.close();
    }
}

 

In this example, a finally block has been used to ensure that a resource is closed, regardless of whether the try statement executes normally or is terminated abruptly. 

Must Read Static Blocks In Java and Hashcode Method in Java

Advantages of Exception Handling in Java

Exception handling in Java is a crucial mechanism that ensures smooth program execution by managing runtime errors. It prevents abrupt program termination and provides a structured way to handle unexpected issues. Java uses try, catch, finally, and throw to detect, handle, and recover from exceptions, making code more robust and maintainable. Proper exception handling improves program stability, debugging, and error management.

  • Provision to Complete Program Execution

Exception handling allows the program to continue running even if an error occurs. Without exception handling, an unhandled exception would cause an abrupt program termination. By using try-catch blocks, developers can catch the exception and take corrective actions, ensuring the program runs smoothly without unexpected crashes. This feature is especially useful in applications that require continuous execution, such as banking systems or online transactions.
 

  • Easy Identification of Program Code and Error-Handling Code

Exception handling separates normal code from error-handling logic, improving readability and maintainability. Instead of mixing error-checking conditions throughout the program, Java allows developers to handle exceptions separately using catch blocks. This makes the main program logic cleaner and more understandable while keeping error-handling mechanisms centralized and efficient.
 

  • Propagation of Errors

Java allows exceptions to be propagated up the call stack using the throws keyword. This means that if a method does not handle an exception, it can pass it to the caller method, which can then handle it at a higher level. This approach is beneficial for large applications where errors need to be handled centrally instead of at every method level, simplifying debugging and maintenance.
 

  • Meaningful Error Reporting

Java exceptions provide detailed error messages and stack traces that help developers quickly identify and resolve issues. The getMessage() and printStackTrace() methods in Java’s Exception class provide insights into where and why the error occurred. This structured error reporting helps in debugging by pinpointing the exact source of the problem, making troubleshooting more efficient.
 

  • Identifying Error Types

Exception handling helps differentiate between checked and unchecked exceptions, enabling developers to implement appropriate handling mechanisms. Checked exceptions must be handled explicitly using try-catch or throws, ensuring potential errors are addressed. Unchecked exceptions, such as NullPointerException or ArithmeticException, are runtime errors that can be avoided with proper validation and coding practices. Understanding these distinctions helps write more reliable and error-free programs.

Frequently Asked Questions

When to use try-catch?

Use try-catch when you expect code might throw exceptions and want to handle them gracefully without crashing the program.

What are the five keywords used in java exception handling?

Java exception handling uses five keywords, try, catch, throw, throws, and finally.

How are the exceptions handled in Java? Specify one method.

The most basic method of handling exceptions is try-catch. Put the code in the try block, and any Java exceptions the code throws will be caught by one or more catch blocks followed by the try block.

Which keyword is used to throw an exception?

The throws keyword is used to specify which exceptions a method can throw, whereas the throw keyword is used to throw an exception explicitly within a method or block of code.

Can we throw an exception manually?

Using the throw keyword, we can explicitly throw a user-defined or predefined exception. To explicitly throw an exception, we must first create the class and then use the throw keyword to throw its object.

Can we catch and throw the same exception in a program?

We can do things like this in the catch block and then rethrow the exception. As a result, a higher level is notified that a system exception has occurred.

Conclusion

In this article, we learned Java Exception Handling, an essential mechanism for handling runtime errors and ensuring program stability. We discussed key concepts such as try-catch blocks, finally, throw, and throws, along with checked and unchecked exceptions. Proper exception handling improves code robustness and maintainability, making Java applications more reliable. Understanding these concepts allows developers to write efficient and error-free programs.

Recommended Readings:

Live masterclass