Exceptions
Exceptions
Exceptions
In the java exception class hierarchy, the class at the top is the Throwable class, which is a direct
subclass of the Object class. Throwable has two direct subclasses Exception and Error, which has again
respective sub-classes The diagram below shows the standard exception and error classes defined in
Java, organized in the Java exceptions hierarchy.
Errors
Error caused by the lack of system resources such as heap memory is not available etc. Errors are
non-recoverable. During the runtime of a program if any error occurs we will not be able to handle
it.
Error is a subclass of Throwable that indicates serious problems that a reasonable application
should not try to catch.
Handling specific errors:
Java Errors such as OutOfMemoryError, StackOverflowError, etc., are typically caused by problems with
the JVM or system resources. While you cannot recover from such errors in most cases, you can handle
them or mitigate their effects by:
In Java, exceptions are divided into two types: checked exceptions and unchecked exceptions.
Checked exceptions
Unchecked exceptions
Checked Exceptions
Checked exceptions are exceptions that must be either caught or declared in the
method’s throws clause. They extend the Exceptionclass but do not extend RuntimeException.
The Java compiler requires that checked exceptions are explicitly handled (caught) within a try-
catch block or declared to be thrown by the method using the throws keyword.
Common examples are IOException, SQLException, and ClassNotFoundException.
Checked exceptions are generally recoverable.
Handling: Because these exceptions are checked at compile time, developers must handle them,
which can result in more robust code. If a checked exception is not handled properly, the code
will fail to compile.
Use Case: Checked exceptions are commonly used for recoverable conditions in which the caller
can reasonably expect to handle the exception.
Unchecked exceptions
Unchecked exceptions are those that are not checked during compile-time. They derive from
the RuntimeException class and can occur at any time during program execution.
Common examples are NullPointerException, ArrayIndexOutOfBoundsException, and
IllegalArgumentException.
Handling: Developers are not required to handle unchecked exceptions, so they can either catch
them or let them propagate up the call stack. This can result in simpler code, but it can also
cause runtime errors if not managed properly.
Unchecked exceptions are commonly used for programming errors, such as logic errors or
improper API usage, from which the caller cannot reasonably be expected to recover.
In Java, exceptions are handled using a combination of try, catch, throw, throws, and finally blocks.
throw Vs throws
throw keyword:
Used in method signatures to declare that a method might throw one or more exceptions, which
must be handled by the caller of the method.
1. Catch Specific Exceptions: Always catch the most specific exception first and then more general
exceptions later. This allows you to handle different errors differently.
2. Use finally for Cleanup: Always use finally to clean up resources (like closing files, database
connections, etc.) to avoid resource leaks.
3. Don’t Use Exceptions for Control Flow: Exceptions should not be used for normal control flow (e.g.,
using exceptions to exit a loop). They are intended for exceptional conditions that you want to
handle explicitly.
4. Log Exceptions: Log exceptions to help debug issues in production. This can be done using logging
frameworks like SLF4J, Log4j, or Java's built-in logging.
5. Handle Exceptions at the Right Level: Handle exceptions at the appropriate level in your application.
Don’t catch exceptions too early in the program; let them propagate up if they can’t be handled
effectively at the current level.
6. Provide Useful Messages: When throwing or catching exceptions, provide meaningful error
messages that can help diagnose the problem.
try-with-resources
In Java, the finally block is a critical part of exception handling, designed to ensure that a block of
code runs regardless of whether an exception occurs. The typical use case for a finally block is to
release resources, close connections, or clean up after a try block, which may throw an exception.
However, there are some scenarios where the finally block might not execute.
While the finally block is intended to always run, there are a few specific circumstances where it
might not:
o JVM Termination
o Power Failure or Hardware Crash
o Infinite Loops or Blocking Calls
To ensure resources are always released properly, especially when dealing with I/O operations, Java 7
introduced the try-with-resources statement. This feature ensures that each resource is closed at the
end of the statement, regardless of whether an exception is thrown.
In this example, the FileInputStream is automatically closed at the end of the try block, ensuring
proper resource cleanup without the need for an explicit finally block.
finally()
The finally block is part of exception handling and is used to define a block of code that will be executed
after a try block, regardless of whether an exception was thrown or not. The finally block is typically
used to release resources, such as closing files, closing database connections, or releasing network
resources, that were acquired during the execution of the try block.
Guaranteed Execution: The finally block always executes after the try block finishes, whether an
exception is thrown or not.
Even with a Return Statement: If a return statement is encountered in the try block,
the finally block will still execute before the method returns.
Execution After Exception: If an exception is thrown in the try block and caught by a catch block,
the finally block will still execute after the catch block.
Exception Handling with finally: If an exception occurs inside the finally block, it will propagate, but
the code after the finally block may not execute.
The finally block can exist with or without a catch block, but it must be preceded by a try block.
No, you cannot have a finally block without a try block in Java. The finally block is always associated with
a try block (and optionally a catch block) in Java's exception handling mechanism. The purpose of
the finally block is to ensure that certain cleanup actions (like closing resources) are always performed,
regardless of whether an exception is thrown or caught.
Since finally is part of the exception handling mechanism, it must be tied to a try block. Without
a try block, the concept of "exception handling" doesn’t apply, and thus the finally block is not required.