Error Handling in Java: try/catch and Beyond — A Complete Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Error Handling is Critical for a Java Developer

Any program that goes beyond "Hello, World!" encounters unexpected situations: the user enters letters instead of numbers, a file is not found, the network is unavailable. In Java, a powerful and elegant mechanism of exceptions has been developed for these cases. Competent error handling is not just "turning a blind eye to the problem," but creating resilient, predictable, and secure code.

In this article, we will analyze not only the classic try/catch construct, but also advanced techniques: try-with-resources, creating custom exceptions, and best practices that will help you write professional Java code.



1. Basics: Exception Hierarchy and the try/catch/finally Construct

Before catching errors, you need to understand their nature. In Java, all exceptions are descendants of the Throwable class. The main branches are Exception (exceptions that can and should be handled) and Error (critical JVM errors that are pointless to handle).

The key division within Exception is into checked and unchecked exceptions.

  • Checked exceptions (e.g., IOException, SQLException) — the compiler forces you to handle them. These are predictable external failures.
  • Unchecked exceptions (descendants of RuntimeException: NullPointerException, ArrayIndexOutOfBoundsException) — logic errors in the program. The compiler does not require handling them, but that doesn't mean they can be ignored.


Basic try-catch-finally Construct

The most common way to handle errors is the try block, which contains the "dangerous" code, and one or more catch blocks for catching specific types of exceptions.

import java.io.*;

public class ReadFileExample { public static void main(String[] args) { BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("data.txt")); String line = reader.readLine(); System.out.println("Read: " + line); } catch (FileNotFoundException e) { System.err.println("Error: File not found! " + e.getMessage()); } catch (IOException e) { System.err.println("Input/Output error: " + e.getMessage()); } finally { // finally ALWAYS executes, even if there was an exception or return try { if (reader != null) { reader.close(); // Important to close the resource } } catch (IOException e) { System.err.println("Error closing file: " + e.getMessage()); } } }}

Important: The finally block is needed for guaranteed resource cleanup (closing files, database connections). However, starting from Java 7, a more elegant way appeared.



2. Modern Approach: try-with-resources (Java 7+)

Forgetting to close a file or connection is one of the most common mistakes for beginners. The try-with-resources construct automatically closes all resources that implement the AutoCloseable (or Closeable) interface. The code becomes shorter, cleaner, and safer.

import java.io.*;

public class TryWithResourcesExample { public static void main(String[] args) { // Resources are declared in parentheses after try try (BufferedReader reader = new BufferedReader(new FileReader("data.txt")); BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {

String line; while ((line = reader.readLine()) != null) {

Blogs

Book Recommendations