1. Checked Exceptions: These exceptions are checked at compile-time, and the compiler forces you to handle them using either a try-catch block or by declaring them in the method signature using the throws keyword. Examples of checked exceptions include IOException, SQLException, etc.
2. Unchecked Exceptions: Also known as runtime exceptions, these exceptions are not checked at compile-time, and the compiler does not force you to handle them explicitly. Examples of unchecked exceptions include NullPointerException, ArrayIndexOutOfBoundsException, etc.
Now, let's look at the basic structure and keywords used in exception handling:
try
{ // Code that may throw an exception }
catch (ExceptionType1 e1) { // Exception handler for ExceptionType1 }
catch (ExceptionType2 e2) { // Exception handler for ExceptionType2 }
finally { // Optional finally block } |
· try block: You enclose the code that might throw an exception inside a try block. If an exception occurs within the try block, it is thrown, and the control is transferred to the nearest catch block.
· catch block: If an exception occurs within the try block, it is caught by the corresponding catch block. You can have multiple catch blocks to handle different types of exceptions. Each catch block specifies the type of exception it can handle.
· finally block: The finally block is optional and is used to specify code that must be executed regardless of whether an exception occurs or not. It is typically used for cleanup tasks, such as closing resources like files or database connections. The finally block is executed even if an exception is thrown and not caught by any catch block.
· throw statement: You can explicitly throw
an exception using the throw statement. This allows you to create and
throw custom exceptions or propagate exceptions to the calling code.
Now, let's see an example that demonstrates exception handling in Java:
import
java.io.FileReader; import
java.io.IOException;
public
class ExceptionHandlingExample { public static void main(String[] args) { FileReader fileReader = null; try { fileReader = new
FileReader("example.txt"); // Code that works with the file } catch (IOException e) { // Exception handler for IOException System.out.println("An error
occurred while reading the file: " + e.getMessage()); } finally { // Cleanup code if (fileReader != null) { try { fileReader.close(); } catch (IOException e) {
System.out.println("Error while closing the file: " +
e.getMessage()); } } } } } |
In this example, we have a main method that attempts to read a file using a FileReader. The FileReader constructor may throw an IOException, so we enclose it in a try block. If an IOException occurs, the control is transferred to the corresponding catch block where we handle the exception by printing an error message.
In the finally block, we close the FileReader to ensure proper cleanup, even if an exception occurs or not. We use a nested try-catch block within the finally block to handle any IOException that may occur while closing the file.
By using exception handling, we can gracefully handle exceptional conditions and ensure that our program continues to run smoothly even in the presence of errors. It helps in separating the error-handling logic from the regular program flow and promotes code reusability and maintainability.
0 Comments