Try Catch
Java exception handling — try-catch-finally, multi-catch, try-with-resources, and the patterns senior developers use to write resilient enterprise code.
Last reviewed: January 2025
🔍 What Is It?
Exception Hierarchy:
Throwable
├── Error (JVM-level, do not catch)
│ ├── OutOfMemoryError
│ └── StackOverflowError
└── Exception
├── RuntimeException (unchecked — no throws declaration needed)
│ ├── NullPointerException
│ ├── IllegalArgumentException
│ ├── IllegalStateException
│ └── IndexOutOfBoundsException
└── Checked Exceptions (must declare or handle)
├── IOException
├── SQLException
└── ParseExceptionChecked vs Unchecked:
- →Checked — compiler forces you to handle or declare with throws. Represents recoverable conditions (file not found, network timeout).
- →Unchecked (RuntimeException) — compiler does not require handling. Represents programming errors (null pointer, illegal argument).
try-with-resources (Java 7+):
Automatically closes any AutoCloseable resource when the block exits, even if an exception occurs.
🎯 Why Do We Need It?
Exception handling is essential for:
- →Resilience — handle expected failures (network timeout, DB unavailable) gracefully
- →Resource cleanup — always close files, connections, streams (try-with-resources)
- →Error reporting — log the full stack trace for debugging
- →User experience — show meaningful error messages, not stack traces
- →Transaction management — rollback transactions on failure
Without exception handling, any unexpected condition crashes the entire application.
🏗️ What Happens in Real Projects?
In enterprise Spring Boot applications:
- →Service methods catch specific exceptions and translate them to domain exceptions
- →Controllers use @ExceptionHandler or @ControllerAdvice to translate exceptions to HTTP responses
- →Repository layer wraps DataAccessException into domain-specific exceptions
- →try-with-resources is used for every I/O operation
- →Global exception handlers log and return structured error responses
⚙️ How It Works
Exception Propagation:
- Exception is thrown at the point of failure
- JVM searches up the call stack for a matching catch block
- First matching catch block executes
- If no catch found, JVM prints stack trace and terminates the thread
finally block:
Runs after try and catch, regardless of outcome. Used for cleanup that must happen even if an exception occurs. Not needed for resource cleanup if using try-with-resources.
Exception chaining:
When catching one exception and throwing another, always include the original as the cause: throw new ServiceException("message", originalException). This preserves the full diagnostic chain.
💻 Example
Exception Handling in Enterprise Code — Production-quality exception handling patterns.
🤔 Common Confusions
❓ Should I catch Exception or specific exception types?
Always catch the most specific exception type you can handle. Catching Exception (or worse, Throwable) swallows unexpected errors silently. The only legitimate use of catch(Exception e) is in a top-level handler (like @ExceptionHandler) where you log and return an error response. In service/repository code, catch specific exceptions.
❓ What is the difference between checked and unchecked exceptions?
Checked exceptions (extends Exception but not RuntimeException) must be declared in throws or handled with try-catch. They represent conditions the caller can reasonably recover from (file not found, network error). Unchecked exceptions (extends RuntimeException) represent programming errors — invalid arguments, null pointers, illegal state. In modern Java, most frameworks use unchecked exceptions exclusively to avoid the boilerplate of checked exception declarations.
❓ Does finally always run?
Almost always. Exceptions where finally does NOT run: (1) System.exit() is called, (2) JVM crashes, (3) the thread is killed. In normal operation — including when an exception is thrown — finally always runs. This makes it reliable for cleanup like releasing locks, closing connections, and logging.
🚨 Common Production Issues
Swallowing exceptions silently — catch(Exception e) {} with no logging or rethrow makes debugging impossible. Always log or rethrow.
Losing the original exception — throw new ServiceException("msg") without the cause loses the stack trace. Always: throw new ServiceException("msg", originalException).
Catching Error — OutOfMemoryError and StackOverflowError indicate JVM-level problems. Catching them gives a false sense of recovery. Let them propagate.
Exception in finally block — if finally throws an exception, the original exception is lost. Use try-with-resources or suppress exceptions carefully.
✅ Best Practices
Use try-with-resources for all AutoCloseable resources — never rely on finally for resource cleanup.
Always include the original exception as the cause when wrapping: throw new AppException("msg", cause).
Never swallow exceptions silently — always log at minimum.
Catch specific exceptions, not Exception or Throwable.
Use custom exception hierarchy: AppException -> ServiceException, NotFoundException, ValidationException.
Log exceptions at the boundary where they are handled, not at every layer.
🏛️ Architect's Note
In Spring Boot, define a clear exception hierarchy: a base AppException (unchecked), then domain-specific subclasses (UserNotFoundException, InsufficientFundsException, ValidationException). Map these to HTTP status codes in @ControllerAdvice. Service layer throws domain exceptions; controller layer never catches — the advice handles it. This keeps controllers thin and exception handling centralized.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
Core Java Interview Prep
Practice interview questions that connect directly to this technology track.
↗ Where this topic fits
Core Java Technology Guide
Return to the Core Java learning hub.
Backend Engineer Career Path
A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Sources
Sources / References
Use these Core Java references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide Core Java learning path
Browse the full Core Java topic collection and learning order on SplashRide.
Core Java Interview Prep
Practice Core Java interview questions and scenario-based answers.
Backend Engineer Career Path
A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Throws
The throws keyword, checked vs unchecked exception design, and why modern Java frameworks moved away from checked exceptions.
Custom Exceptions
Building a clean exception hierarchy for enterprise applications — naming conventions, when to extend checked vs unchecked, and how Spring Boot maps them to HTTP responses.