In Java, exceptions are divided into checked and unchecked exceptions.
Exception, but not from RuntimeException. The compiler requires them to be explicitly handled with try-catch or declared in throws.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).
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
Story
In a banking API project, I/O errors were throwing
RuntimeExceptioninstead 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 Exceptionin 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.