Introduction to Error Handling in Java
In the world of programming, errors are inevitable. They occur for various reasons: incorrect user input, file unavailability, logic errors in the program, or network failures. In the Java language, there is a powerful and flexible mechanism for managing such situations — exceptions. Proper error handling is not just good practice, but a guarantee of the stability, reliability, and security of your application.
In this article, we will thoroughly examine how error handling works in Java, starting with the basic try/catch construct and ending with advanced techniques such as try-with-resources and creating custom exceptions. You will learn the differences between checked and unchecked exceptions, and how to use them correctly.
Basics: the try/catch and finally construct
Try and catch blocks
The heart of exception handling in Java is the try/catch construct. Code that may throw an exception is placed inside a try block. If an exception occurs in this block, execution immediately transfers to the corresponding catch block, where the exception is handled.
public class Main { public static void main(String[] args) { try { int result = 10 / 0; // This will cause ArithmeticException System.out.println("Result: " + result); } catch (ArithmeticException e) { System.out.println("Error: division by zero!"); e.printStackTrace(); // Prints the call stack for debugging } System.out.println("Program continues..."); }}Note: the line System.out.println("Result: " + result); will not execute because the exception occurred earlier. However, the program will not "crash" — control transfers to catch, and execution continues after the try/catch block.
Multiple catch blocks
A single try block can have multiple catch blocks to handle different types of exceptions. It is important to remember that more specific exceptions must be listed before more general ones.
try { String str = null; System.out.println(str.length()); // NullPointerException int[] arr = new int[5]; arr[10] = 100; // ArrayIndexOutOfBoundsException} catch (NullPointerException e) { System.out.println("NullPointerException: " + e.getMessage());} catch (ArrayIndexOutOfBoundsException e) { System.out.println("ArrayIndexOutOfBoundsException: " + e.getMessage());} catch (Exception e) { // General handler for all other exceptions System.out.println("General error: " + e.getMessage());}The finally block
The finally block is a special block that always executes, regardless of whether an exception was thrown or not. It is ideal for releasing resources: closing files, database connections, or sockets.
import java.io.*;
public class FileExample { public static void main(String[] args) { FileInputStream file = null; try { file = new FileInputStream("test.txt"); int data = file.read(); System.out.println((char) data); } catch (FileNotFoundException e) { System.out.println("File not found!"); } catch (IOException e) { System.out.println("Input/output error!"); } finally { try { if (file != null) { file.close(); // Close the file in any case } } catch (IOException e) { System.out.println("Error closing the file!"); } } }}Even if an exception occurs in the try or catch block, the finally block will still execute.