ProgrammingBackend Developer

What is the difference between checked and unchecked exceptions in Java, how to properly design error handling, and what mistakes should be avoided when using them?

Pass interviews with Hintsage AI assistant

Answer

In Java, exceptions are divided into checked and unchecked exceptions.

  • Checked exceptions — inherit from Exception, but not from RuntimeException. The compiler requires them to be explicitly handled with try-catch or declared in throws.
  • Unchecked exceptions — inherit from RuntimeException. The compiler does not require their mandatory handling.
public void readFile(String file) throws IOException { /* ... */ } // checked public void divide(int a, int b) { int res = a/b; } // unchecked (ArithmeticException)

The main nuance is that checked exceptions are used for expected, recoverable situations (e.g., I/O errors), whereas unchecked exceptions are for programming logic errors or critical situations from which recovery is not possible (e.g., NullPointerException).

Trick Question

Question: Should unchecked exceptions be handled or declared in throws if your method can throw them?

Answer: No. The compiler does not require checking or declaring unrecoverable (unchecked) exceptions. Their handling is at your discretion; you can use try-catch, but more often — let them "fall" to a global handler.

public void foo() { throw new IllegalArgumentException(); } // No handling or declaration required

Examples of real errors due to a lack of knowledge of the nuances of the topic


Story

In a banking API project, I/O errors were throwing RuntimeException instead of checked. As a result, clients were not forced to handle them, leading to incorrect operation when the connection to the server was lost, and the application "crashed" without notifying the user.


Story

A developer declared an excessive number of throws Exception in method signatures (e.g., database), causing all the used methods above to be forced into either try-catch or also throws. This cluttered the code, worsened readability, and complicated refactoring.


Story

In one microservice, all exceptions were caught with a general catch (Exception e). This intercepted unchecked exceptions (e.g., NullPointerException), leading to the "silent" ignoring of critical errors — the service operated with incorrect data.