Skip to content

Exceptions and Exception Handling in Java

In Java, exceptions are events that disrupt the normal flow of the program’s execution. They are used to handle errors and other exceptional conditions in a controlled way. When an exception occurs, the normal execution flow of the program is disrupted, and the exception is thrown. If the exception is not handled, it can cause the program to terminate unexpectedly.

Java provides a powerful mechanism to handle exceptions through exception handling.


What is an Exception?

An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions. Exceptions can be caused by many things, such as:

  • Trying to access a null object reference.
  • Dividing by zero.
  • Trying to read a file that doesn’t exist.
  • Network connectivity issues.

Exceptions can be classified into two types:

  1. Checked Exceptions: These are exceptions that must be either caught or declared in the method signature. They are checked at compile-time. Examples: IOException, SQLException.

  2. Unchecked Exceptions: These are exceptions that are not required to be declared or handled. They are checked at runtime. Examples: NullPointerException, ArithmeticException.


Basic Syntax for Exception Handling

Java provides the following keywords for exception handling:

  1. try: Used to define a block of code where exceptions might occur.
  2. catch: Used to catch exceptions thrown by the try block.
  3. finally: Used to define a block of code that always executes, regardless of whether an exception was thrown or not. It is often used for cleanup code like closing files or releasing resources.
  4. throw: Used to explicitly throw an exception.
  5. throws: Used in a method declaration to specify that a method can throw an exception.

Example 1: Basic Try-Catch Block

Here is a basic example demonstrating how exceptions can be handled in Java using try, catch, and finally blocks.

java
public class ExceptionHandlingExample {
    public static void main(String[] args) {
        try {
            // Code that might throw an exception
            int result = 10 / 0;  // This will cause ArithmeticException (divide by zero)
        } catch (ArithmeticException e) {
            // Code to handle the exception
            System.out.println("Error: Division by zero is not allowed.");
        } finally {
            // Code that will always run, even if an exception occurs
            System.out.println("This block is always executed.");
        }
    }
}

Explanation:

  • The try block contains code that might throw an exception. In this case, dividing by zero will throw an ArithmeticException.
  • The catch block catches the exception and handles it by printing a message.
  • The finally block will always be executed regardless of whether an exception was thrown or not. It is typically used for cleanup tasks like closing files or database connections.

Output:

Error: Division by zero is not allowed.
This block is always executed.

Example 2: Multiple Catch Blocks

You can handle multiple types of exceptions using multiple catch blocks.

java
public class MultiCatchExample {
    public static void main(String[] args) {
        try {
            // Code that might throw different exceptions
            int[] numbers = new int[5];
            numbers[10] = 30;  // This will cause ArrayIndexOutOfBoundsException
        } catch (ArithmeticException e) {
            System.out.println("Error: Arithmetic exception occurred.");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Error: Array index is out of bounds.");
        } catch (Exception e) {
            System.out.println("Error: Some other exception occurred.");
        } finally {
            System.out.println("This block is always executed.");
        }
    }
}

Explanation:

  • The try block tries to assign a value to an invalid array index, which throws an ArrayIndexOutOfBoundsException.
  • There are three catch blocks:
    • One for ArithmeticException.
    • One for ArrayIndexOutOfBoundsException.
    • A generic catch block that will handle any other exceptions that do not match the above.
  • The finally block is executed regardless of whether an exception occurs or not.

Output:

Error: Array index is out of bounds.
This block is always executed.

Example 3: Throwing Exceptions

You can explicitly throw an exception using the throw keyword.

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

    // Method to check if the age is valid
    public static void validateAge(int age) {
        if (age < 18) {
            throw new IllegalArgumentException("Age must be 18 or older.");
        }
        System.out.println("Age is valid.");
    }
}

Explanation:

  • The method validateAge() checks if the age is less than 18. If so, it explicitly throws an IllegalArgumentException with a message.
  • The exception is caught in the catch block and the message is printed.

Output:

Age must be 18 or older.

Example 4: Declaring Exceptions Using throws

If a method can throw a checked exception, it must either handle the exception or declare it using the throws keyword.

java
import java.io.IOException;

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

    // Declaring that this method can throw an IOException
    public static void readFile() throws IOException {
        // Code that might throw an IOException
        throw new IOException("File not found.");
    }
}

Explanation:

  • The readFile() method declares that it can throw an IOException using the throws keyword.
  • The method is called inside a try block, and any thrown IOException is caught and handled in the catch block.

Output:

Error: File not found.

Checked vs Unchecked Exceptions

  • Checked Exceptions:

    • These exceptions are checked at compile-time.
    • The programmer must either catch or declare these exceptions in the method signature.
    • Examples: IOException, SQLException, ClassNotFoundException.
  • Unchecked Exceptions:

    • These exceptions are not checked at compile-time and are typically caused by programming errors.
    • These exceptions do not need to be declared or handled.
    • Examples: NullPointerException, ArithmeticException, ArrayIndexOutOfBoundsException.

Commonly Used Built-in Exceptions in Java

  • ArithmeticException: Thrown when an arithmetic operation (like division by zero) is attempted.
  • NullPointerException: Thrown when trying to access an object reference that is null.
  • ArrayIndexOutOfBoundsException: Thrown when trying to access an invalid array index.
  • IOException: Thrown when there is an input/output operation failure (like reading a file).
  • SQLException: Thrown when there is an issue with database operations.
  • ClassNotFoundException: Thrown when the JVM cannot find a class that is being loaded dynamically.

Conclusion

  • Exceptions provide a way to handle errors and other exceptional conditions in a Java program.
  • Java supports checked and unchecked exceptions and provides various keywords like try, catch, throw, throws, and finally to handle exceptions.
  • Proper exception handling allows you to build robust applications that can gracefully handle runtime errors and edge cases.
  • You can throw exceptions explicitly using the throw keyword and declare exceptions using throws in method signatures.

By understanding exception handling, you can ensure your Java applications handle errors effectively and continue execution without crashing unexpectedly.

J2J Institute private limited