Error Handling in Java: From try/catch to Advanced Techniques

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

Error Handling in Java: From try/catch to Advanced Techniques



Exception handling is one of the cornerstones of a reliable Java application. Most developers are familiar with the basic try-catch-finally construct, but at an advanced level, Java offers much more flexible and efficient tools. In this article, we will cover not only the classic approach but also modern features such as multi-catch, try-with-resources, creating custom exceptions, and handling strategies. This material is intended for developers who already write confidently in Java and want to deepen their knowledge.



1. The Classic: try-catch-finally and Its Nuances



The basic construct remains the foundation. However, at an advanced level, it is important to understand how it works under the hood and what mistakes even experienced programmers make.



Consider an example with file input/output:



import java.io.*;

public class ClassicExample { public static void main(String[] args) { BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("file.txt")); String line = reader.readLine(); System.out.println(line); } catch (IOException e) { System.err.println("Read error: " + e.getMessage()); } finally { try { if (reader != null) { reader.close(); } } catch (IOException e) { System.err.println("Close error: " + e.getMessage()); } } }}


Key points for an advanced level:

  • Order of catch blocks: more specific exceptions must come first. If you place Exception before IOException, the compiler will throw an error.
  • The finally block always executes, even if there is a return in try or catch. This is important for releasing resources.
  • Exception suppression: if an exception occurs in both try and finally, the exception from finally "swallows" the first one. To avoid this, use Throwable.getSuppressed().


2. Multi-catch: Elegance and Readability



Starting with Java 7, it became possible to combine multiple exceptions in a single catch block. This significantly reduces code duplication.



Without multi-catch, the code looks cumbersome:



try {    // code that may throw IOException or SQLException} catch (IOException e) {    logger.error("I/O error", e);    throw new RuntimeException(e);} catch (SQLException e) {    logger.error("Database error", e);    throw new RuntimeException(e);}


With multi-catch, it becomes concise:



try {    // code} catch (IOException | SQLException e) {    logger.error("Resource error", e);    throw new RuntimeException(e);}


Important: the variable e in multi-catch is final (or effectively final). You cannot assign it another value. This is done for type safety.



3. Try-with-resources: Automatic Resource Management



This is perhaps the most powerful improvement for resource handling. It automatically closes resources that implement the AutoCloseable (or Closeable) interface.



Compare with the classic example above. Here is how it looks with try-with-resources:



import java.io.*;

public class TryWithResourcesExample { public static void main(String[] args) { try (BufferedReader reader = new BufferedReader(new FileReader("file.txt")); BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {

Strin

Blogs

Book Recommendations