English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In this tutorial, you will learn how to handle exceptions in Java with the help of examples. To handle exceptions, we will use the try ... catch ... finally blocks.
In the previous tutorial, we learned about exceptions. Exceptions are unexpected events that occur during program execution.
In Java, we use the exception handling components try, catch, and finally blocks to handle exceptions.
To catch and handle exceptions, we place the try...catch...finally code block around the code that may generate an exception. The finally block is optional.
The syntax of try...catch...finally is:
try {}} // Code } catch (ExceptionType e) { // Catch block } finally { //Finally block }
Code that may generate an exception is placed in the try block.
Each try block should be followed by a catch or finally block. When an exception occurs, it will be caught by the block following the catch.
Catch blocks cannot be used alone and must follow the try block.
class Main { public static void main(String[] args) { try {}} int divideByZero = 5 / 0; System.out.println("The remaining code in the try block"); } catch (ArithmeticException e) { System.out.println("ArithmeticException => "); + e.getMessage()); } } }
Output result
ArithmeticException => / divided by zero
In this instance
We divide the number by 0 in the try block. This produces an ArithmeticException.
When an exception occurs, the program skips the remaining code in the try block.
In this case, we create a catch block to handle ArithmeticException. Therefore, the statements within the catch execution block are executed.
If all statements in the try block do not generate an exception, the catch code block is skipped.
For each try block, there can be zero or more catch blocks.
The parameter type of each catch block indicates the exception types that can be handled. Multiple catch blocks allow us to handle each exception in a different way.
class ListOfNumbers { public int[] arrayOfNumbers = new int[10]; public void writeList() { try {}} arrayOfNumbers[10] = 11; } catch (NumberFormatException e1) { System.out.println("NumberFormatException => " + e1.getMessage()); } catch (IndexOutOfBoundsException e2) { System.out.println("IndexOutOfBoundsException => "); + e2.getMessage()); } } } class Main { public static void main(String[] args) { ListOfNumbers list = new ListOfNumbers(); list.writeList(); } }
Output result
IndexOutOfBoundsException => Index 10 out of bounds for length 10
In this example, we declare an array of size10 an integer array arrayOfNumbers.}}
We know that array indices always start from 0. Therefore, when we try to assign a value to the index10IndexOutOfBoundsException occurs when assigning a value because the boundary of the arrayOfNumbers array is from 0 to9.
When an exception occurs in the try block
The exception is thrown to the first catch block. The first catch block does not handle the IndexOutOfBoundsException exception, so it is passed to the next catch block.
The second catch block in the above example is the appropriate exception handler because it handles IndexOutOfBoundsException. Therefore, it is executed.
For each try block, there can be only one finally block.
The finally block is optional. However, if defined, it will always execute (even if no exception occurs).
If an exception occurs, it is executed after the try...catch block. If no exception occurs, it is executed after the try block.
The basic syntax of the finally block is:
try {}} //code } catch (ExceptionType1 e1) { // catch block } catch (ExceptionType1 e2) { // catch block } finally { //The finally block always executes }
class Main { public static void main(String[] args) { try {}} int divideByZero = 5 / 0; } catch (ArithmeticException e) { System.out.println("ArithmeticException => "); + e.getMessage()); } finally { System.out.println("The finally block always executes"); } } }
Output result
ArithmeticException => / divided by zero The finally block always executes
In this example, we divide a number by zero. This throws an ArithmeticException that is caught by the catch block, and the finally block always executes.
Using the finally block is considered a good practice. This is because it contains important cleanup code, such as
Code that may be accidentally skipped by return, continue, or break statements
Closing a file or connection
We have mentioned that finally always executes, usually like this. However, in some cases, the finally block does not execute:
Using the System.exit() method
Exception occurs in the finally block
Thread is terminated
Let us take an example, we try to create a new file using FileWriter and write data using PrintWriter.
import java.io.*; class ListOfNumbers { private int[] list = new int[10]; public ListOfNumbers() { //Store integer values in the list array for (int i = 0; i < 10; i++) { list[i] = i; } } } public void writeList() { PrintWriter out = null; try {}} System.out.println("Enter try statement"); //Create a new file OutputFile.txt out = new PrintWriter(new FileWriter("OutputFile.txt")); //Write values from the list array to the newly created file for (int i = 0; i < 10; i++) { out.println("Value at: "); + i + " = " + list[i]; } } catch (IndexOutOfBoundsException e1) { System.out.println("IndexOutOfBoundsException => "); + e1.getMessage()); } catch (IOException e2) { System.out.println("IOException => "); + e2.getMessage()); } finally { //Check if the PrintWriter is open if (out != null) { System.out.println("Close PrintWriter"); out.close(); } else { System.out.println("PrintWriter cannot be opened"); } } } } class Main { public static void main(String[] args) { ListOfNumbers list = new ListOfNumbers(); list.writeList(); } }
When you run this program, there may be two possibilities:
An exception occurs in the try block
The try block executes normally
An exception may occur when creating a new FileWriter. If the specified file cannot be created or written to, an IOException is thrown.
When an exception occurs, we will obtain the following output.
Enter try statement IOException => OutputFile.txt PrintWriter cannot be opened
When no exception occurs and the try block executes normally, we will get the following output.
Enter try statement Close PrintWriter
An OutputFile.txt will be created and will contain the following content
Value at: 0 = 0 Value at: 1 = 1 Value at: 2 = 2 Value at: 3 = 3 Value at: 4 = 4 Value at: 5 = 5 Value at: 6 = 6 Value at: 7 = 7 Value at: 8 = 8 Value at: 9 = 9
Let's try to understand the process of exception handling in detail with the help of the above example.
The figure above describes the program execution flow when an exception occurs while creating a new FileWriter.
To find the method where the exception occurred, the main method calls the writeList() method, which then calls the FileWriter() method to create a new OutputFile.txt file.
When an exception occurs, the runtime system skips the remaining code in the try block.
It starts searching the call stack in reverse order to find a suitable exception handler.
Here, the FileWriter has no exception handler, so the runtime system checks the next method in the call stack, which is writeList.
The writeList method has two exception handlers: one for IndexOutOfBoundsException and another for IOException.
Then, the system processes these handlers in turn.
In this example, the first handler handles IndexOutOfBoundsException. This does not match the IOException thrown by the try block.
Therefore, check which IOException handler is the next one. If it matches the type of the thrown exception, the code in the corresponding catch block will be executed.
After executing the exception handler, the finally block will be executed.
In this scenario, since an exception occurred in the FileWriter, the PrintWriter object out was never opened, so there is no need to close it.
Now, let's assume that no exceptions occur while running the program and the try block executes normally. In this case, an OutputFile.txt will be created and written to.
As is well known, the execution of the finally block is unrelated to exception handling. Since no exception occurred, the PrintWriter was opened and needs to be closed. This is done through the out.close() statement in the finally block.
From Java SE 7Starting from version and higher, we can now catch more than one type of exception with a single catch block.
This can reduce code redundancy and improve the simplicity and efficiency of the code.
Each type of exception that can be handled by a catch block is separated by a vertical bar (|).
Its syntax is:
try {}} // code } catch (ExceptionType1 | Exceptiontype2 ex) { // catch block }
For more information, please visitJava captures multiple exceptions.
try-with-The resources statement is a try statement that has one or more resource declarations.
Its syntax is:
try (resource declaration) { // use of the resource } catch (ExceptionType e1) { // catch block }
Resources are objects that need to be closed when the program ends. They must be declared and initialized in the try statement.
Let's take an example.
try (PrintWriter out = new PrintWriter(new FileWriter("OutputFile.txt"))) { // use of the resource }
try-with-The resources statement is also known asAutomatic resource management. This statement automatically closes all resources at the end of the statement.
For more information, please visitJava try-with-resources statement.