Exception Handling (try-catch-finally, throw/throws)


Table of Contents

  1. Introduction to Exception Handling
  2. What is an Exception?
  3. The Need for Exception Handling in Java
  4. try-catch Block
    • How try-catch works
    • Multiple catch blocks
    • Catching multiple exceptions
  5. finally Block
    • Purpose of finally
    • When is finally executed?
  6. throw Keyword
    • Throwing exceptions explicitly
    • Custom exceptions
  7. throws Keyword
    • Declaring exceptions
    • Propagating exceptions
  8. Common Exception Types in Java
  9. Best Practices for Exception Handling
  10. Summary

1. Introduction to Exception Handling

Exception handling is an essential aspect of programming in Java. It enables developers to deal with runtime errors in a controlled manner. Java provides a robust exception handling mechanism that ensures the smooth execution of the program by preventing abrupt termination due to errors.

In Java, exceptions are objects that describe unusual or exceptional conditions that can occur during the execution of a program. For example, division by zero, accessing an array element out of bounds, or trying to open a file that does not exist are all common exceptions that need to be handled.

This module will cover the try-catch-finally block, throw/throws keywords, and various aspects of exception handling in Java.


2. What is an Exception?

An exception is an event that disrupts the normal flow of a program’s execution. It typically occurs when something goes wrong during the execution of a program, such as invalid user input, file I/O errors, or network failures.

When an exception occurs, it creates an object that contains details about the error, such as the type of error, where it occurred, and a stack trace to help developers identify the root cause of the issue.

There are two types of exceptions in Java:

  1. Checked exceptions: These exceptions must be either caught or declared to be thrown. They are checked at compile-time.
  2. Unchecked exceptions: These exceptions do not need to be explicitly handled. They are subclasses of RuntimeException and occur during runtime.

3. The Need for Exception Handling in Java

Exception handling is crucial for building resilient programs. Without exception handling, if an error occurs, the program may crash or behave unpredictably. With proper exception handling, developers can ensure that their program continues to function or exits gracefully without losing data or leaving operations in an inconsistent state.

Key reasons for using exception handling:

  • Graceful error recovery: Ensures the program can handle errors without abrupt termination.
  • Improved readability and maintainability: Exception handling clarifies where and how errors are dealt with.
  • Control flow management: Enables managing different types of errors in a structured way.

4. try-catch Block

The try-catch block is the cornerstone of exception handling in Java. The try block contains the code that might throw an exception. If an exception occurs, it is caught by the catch block, which allows the program to handle the exception rather than terminating abruptly.

Syntax:

try {
// Code that might throw an exception
} catch (ExceptionType e) {
// Code to handle the exception
}

Example:

public class Example {
public static void main(String[] args) {
try {
int result = 10 / 0; // ArithmeticException occurs here
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
}
}
}

In the above example, the division by zero throws an ArithmeticException. The catch block catches the exception and prints the error message.

Multiple catch blocks:

You can have multiple catch blocks to handle different types of exceptions separately.

public class Example {
public static void main(String[] args) {
try {
String str = null;
System.out.println(str.length()); // NullPointerException
} catch (ArithmeticException e) {
System.out.println("Arithmetic Exception occurred.");
} catch (NullPointerException e) {
System.out.println("Null Pointer Exception occurred.");
}
}
}

Catching multiple exceptions in one block:

From Java 7 onward, multiple exceptions can be caught in a single catch block, reducing redundancy.

try {
int[] numbers = {1, 2, 3};
System.out.println(numbers[5]); // ArrayIndexOutOfBoundsException
} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println("Exception occurred: " + e.getMessage());
}

5. finally Block

The finally block is an optional block that is executed after the try-catch block, regardless of whether an exception was thrown or not. The finally block is commonly used to release system resources like closing files or database connections.

Syntax:

try {
// Code that might throw an exception
} catch (ExceptionType e) {
// Exception handling code
} finally {
// Code to release resources
}

Example:

public class Example {
public static void main(String[] args) {
try {
int result = 10 / 2; // No exception
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
} finally {
System.out.println("This will always be executed.");
}
}
}

When is finally executed?

  • After the try block: The finally block is always executed after the try and catch blocks, even if an exception is thrown.
  • Even if there’s a return statement: The finally block is executed before the method returns, even if there’s a return statement inside the try or catch block.

6. throw Keyword

The throw keyword is used to explicitly throw an exception in Java. This is typically used when the program encounters an error that cannot be handled locally or when it needs to indicate an error condition to the caller.

Syntax:

throw new ExceptionType("Error message");

Example:

public class Example {
public static void main(String[] args) {
try {
validateAge(15); // Throws an exception because age is less than 18
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}

static void validateAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("Age must be 18 or older.");
}
}
}

In this example, the throw keyword is used to throw an IllegalArgumentException if the age is less than 18.


7. throws Keyword

The throws keyword is used in a method signature to declare that a method can throw one or more exceptions. It allows you to propagate exceptions from a method to its caller, making it the responsibility of the caller to handle the exception.

Syntax:

public void methodName() throws ExceptionType {
// Code that may throw an exception
}

Example:

public class Example {
public static void main(String[] args) {
try {
readFile("test.txt");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}

static void readFile(String fileName) throws IOException {
// Code that may throw an IOException
throw new IOException("File not found");
}
}

In the above example, the readFile method declares that it can throw an IOException. The caller (in this case, the main method) must handle it using a try-catch block.


8. Common Exception Types in Java

Java provides a wide range of built-in exceptions. Some of the most common exceptions are:

  • ArithmeticException: Occurs when an illegal arithmetic operation is performed, such as division by zero.
  • NullPointerException: Thrown when the program tries to access a method or field on a null object.
  • ArrayIndexOutOfBoundsException: Occurs when trying to access an index outside the bounds of an array.
  • IOException: Thrown when there’s an I/O failure, such as file not found or network issues.
  • FileNotFoundException: A subclass of IOException that occurs when a file cannot be found.

9. Best Practices for Exception Handling

  1. Catch only those exceptions you can handle: Avoid catching exceptions that you don’t intend to handle. For example, catching Exception can sometimes lead to hiding bugs.
  2. Use specific exception types: Always try to catch specific exceptions (like FileNotFoundException) instead of generic ones (Exception).
  3. Don’t swallow exceptions: If you catch an exception, always handle it properly or log it. Don’t just ignore it.
  4. Use finally for resource management: Always release resources such as file handles, database connections, and sockets in the finally block.

10. Summary

In this module, we explored Java’s exception handling mechanism, focusing on the following key concepts:

  • The try-catch-finally blocks, which help you handle exceptions and ensure the program’s smooth execution.
  • The throw/throws keywords, which allow you to manually throw and declare exceptions in methods.
  • The importance of handling different types of exceptions in a structured manner to ensure program stability.

By understanding and implementing exception handling, developers can build robust Java applications that gracefully handle errors and prevent unwanted crashes.