Custom exceptions & try-with-resources
Design your own exceptions, chain causes, and close resources automatically with AutoCloseable.
Java's built-in exceptions describe generic problems: an illegal argument, a missing file. Your application has its own vocabulary: an InsufficientFundsException, an OrderNotFoundException, a PaymentDeclinedException. In this lesson you will create custom exceptions, chain them to preserve root causes, and use try-with-resources to close files, connections and other resources automatically.
Creating a custom exception#
A custom exception is just a class that extends an exception type:
Notice:
- The constructor passes a message up with
super(message), sogetMessage()works. - Custom exceptions can carry extra data (
shortfall) that callers can use to react sensibly. - The class name says exactly what went wrong, so callers can catch precisely that.
Checked or unchecked?#
Modern Java libraries and frameworks (Spring, Hibernate) lean heavily towards unchecked exceptions. Spring, for instance, translates SQLException into its unchecked DataAccessException hierarchy. Many teams use a small hierarchy of unchecked domain exceptions:
A shared base class lets callers catch "any shop problem" or one specific problem, whichever suits them.
Exception chaining: keep the root cause#
When a low-level exception occurs, you often want to throw a higher-level, more meaningful one. Always pass the original as the cause:
In a printed stack trace, the cause appears as a Caused by: section. Throwing new ConfigException("failed") without the cause would throw away the most important clue.
Also standard: the convention of providing the four constructors (), (String message), (String message, Throwable cause) and (Throwable cause). IDEs can generate them.
The resource problem#
Files, network sockets, database connections and locks must be closed when you are done, or your program leaks them. The old way used finally:
Verbose, easy to get wrong, and it can hide the original exception.
try-with-resources#
Declare resources in parentheses after try. They are closed automatically at the end of the block, in reverse order, even if an exception occurs:
Any object that implements java.lang.AutoCloseable (or its subinterface java.io.Closeable) can be used: readers, writers, streams, Scanner, JDBC Connection/Statement/ResultSet, ExecutorService (Java 19+) and more.
Your own AutoCloseable resource#
Implementing AutoCloseable makes your class work with try-with-resources. Watch the order of events:
The resources are closed before the catch and finally blocks run, and in reverse order of opening.
Suppressed exceptions#
What if the body throws and close() throws too? try-with-resources keeps the body's exception as the main one and attaches the close failure as a suppressed exception, so nothing is lost:
Since Java 9: effectively final resources#
If a resource variable already exists and is (effectively) final, you can name it directly:
Handling exceptions at the right layer#
In a typical application:
- Low-level code (file, database, HTTP) throws or wraps technical exceptions with causes.
- Service code throws meaningful domain exceptions (
OrderNotFoundException). - The top layer (a
mainloop, a web controller, Spring's@ControllerAdvice) catches them, logs the details, and shows the user a friendly message or an HTTP status.
Common mistakes#
- Creating a custom exception for every tiny thing. Reuse
IllegalArgumentExceptionand friends when they fit. - Losing the cause when wrapping (
throw new MyException(e.getMessage())). - Catching an exception just to re-throw it unchanged.
- Forgetting to close resources, or closing them in
finallyby hand when try-with-resources would do. - Making exception classes mutable or giving them heavy logic. They should be simple value carriers.
What's next#
Before we reach the collections framework, there is one more piece to understand: how primitives like int become objects like Integer. Next up: wrapper classes and autoboxing.
Check your understanding
Quick quiz
1.To create a custom unchecked exception, which class should you extend?
2.In
try (A a = new A(); B b = new B()) { ... }, in which order are the resources closed?3.Why pass the original exception as the
causewhen wrapping it in a new exception?
Finished reading?
Mark this lesson complete to track your progress.