Exception Handling in Java

Mohit  UpadhyayMohit Upadhyay
6 min read

On Day 15, we’ll dive into one of the most crucial concepts in Java: Exception Handling. Exception handling is an essential mechanism in Java that helps developers manage runtime errors and maintain the normal flow of an application. Without proper exception handling, an application can crash or behave unexpectedly.

This article will cover the basics of exceptions, the types of exceptions in Java, and how to handle them effectively using try, catch, throw, throws, and finally constructs.


1. What is an Exception?

In Java, an exception is an event that disrupts the normal flow of a program. Exceptions are objects that represent errors or unexpected behavior during program execution.

Exceptions can occur due to various reasons, such as:

  • Dividing by zero.

  • Accessing an array with an invalid index.

  • Trying to open a file that doesn’t exist.

Example:

int a = 10;
int b = 0;
int result = a / b;  // This will cause an ArithmeticException

In the above code, dividing by zero causes an ArithmeticException, terminating the program if not handled properly.


2. Exception Hierarchy in Java

Java exceptions are categorized into a hierarchy that all derive from the base class java.lang.Throwable. There are two main branches of this hierarchy:

  • Checked Exceptions (Compile-time Exceptions): These exceptions are checked at compile-time, and the programmer is required to handle them using a try-catch block or declare them using throws.

    • Example: IOException, SQLException, ClassNotFoundException.
  • Unchecked Exceptions (Runtime Exceptions): These exceptions are not checked during compilation but occur at runtime. They usually occur due to programming mistakes.

    • Example: ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException.

Exception Hierarchy Diagram:

Throwable
   |
   +-- Exception (Checked)
   |     +-- IOException
   |     +-- SQLException
   |
   +-- RuntimeException (Unchecked)
         +-- NullPointerException
         +-- ArithmeticException
         +-- ArrayIndexOutOfBoundsException

3. Handling Exceptions in Java

Java provides a powerful mechanism to handle exceptions using five main keywords:

  1. try: The code that might throw an exception is placed inside a try block.

  2. catch: This block catches and handles the exception.

  3. finally: A block that always executes after the try-catch block, whether an exception is thrown or not.

  4. throw: Used to explicitly throw an exception.

  5. throws: Declares that a method can throw exceptions.

Example of try-catch:

public class Main {
    public static void main(String[] args) {
        try {
            int a = 10;
            int b = 0;
            int result = a / b;  // This line throws an ArithmeticException
        } catch (ArithmeticException e) {
            System.out.println("Cannot divide by zero!");
        }
    }
}

Output:

Cannot divide by zero!

In this example, the ArithmeticException is caught and handled, preventing the program from terminating abnormally.


4. Types of Exceptions

A. Checked Exceptions

These exceptions are checked by the compiler, and the programmer must handle them using try-catch or declare them using the throws keyword.

Example: Handling a Checked Exception (IOException):

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            File file = new File("nonexistentfile.txt");
            FileReader fr = new FileReader(file);  // This throws FileNotFoundException
        } catch (IOException e) {
            System.out.println("File not found!");
        }
    }
}

Output:

File not found!

B. Unchecked Exceptions (Runtime Exceptions)

These exceptions are not checked at compile-time. They occur during runtime due to logical errors in the program.

Example: Handling a Runtime Exception (NullPointerException):

public class Main {
    public static void main(String[] args) {
        String str = null;
        try {
            System.out.println(str.length());  // This throws NullPointerException
        } catch (NullPointerException e) {
            System.out.println("Null value encountered!");
        }
    }
}

Output:

Null value encountered!

5. throw and throws Keywords

A. throw Keyword:

The throw keyword is used to explicitly throw an exception. It can be used to throw both checked and unchecked exceptions.

Example: Using throw to throw an exception:

public class Main {
    public static void main(String[] args) {
        int age = 15;
        if (age < 18) {
            throw new ArithmeticException("Age must be at least 18 to vote");
        }
    }
}

Output:

Exception in thread "main" java.lang.ArithmeticException: Age must be at least 18 to vote

B. throws Keyword:

The throws keyword is used to declare exceptions that a method can throw. It tells the caller of the method that it might throw certain exceptions.

Example: Using throws in Method Declaration:

import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        checkFile();
    }

    public static void checkFile() throws IOException {
        throw new IOException("File not found!");
    }
}

6. finally Block

The finally block is used to execute code regardless of whether an exception was thrown or caught. This is typically used for resource cleanup, such as closing files or database connections.

Example of finally:

public class Main {
    public static void main(String[] args) {
        try {
            int a = 10;
            int b = 0;
            int result = a / b;
        } catch (ArithmeticException e) {
            System.out.println("Cannot divide by zero!");
        } finally {
            System.out.println("Finally block executed.");
        }
    }
}

Output:

Cannot divide by zero!
Finally block executed.
  • In this example, the finally block is executed whether or not the exception is caught.

7. Custom Exceptions

In Java, you can create your own custom exceptions by extending the Exception class (for checked exceptions) or RuntimeException class (for unchecked exceptions). This is useful when you want to represent specific application-level errors.

Example: Creating a Custom Exception:

class AgeException extends Exception {
    public AgeException(String message) {
        super(message);
    }
}

public class Main {
    public static void main(String[] args) {
        try {
            validateAge(15);
        } catch (AgeException e) {
            System.out.println(e.getMessage());
        }
    }

    public static void validateAge(int age) throws AgeException {
        if (age < 18) {
            throw new AgeException("Age must be at least 18 to vote");
        }
    }
}

Output:

Age must be at least 18 to vote

8. Best Practices for Exception Handling

  1. Use Specific Exceptions: Always catch specific exceptions rather than using a general Exception catch block. This improves code readability and debugging.

  2. Avoid Silent Catch Blocks: Do not leave catch blocks empty. If an exception occurs, handle it appropriately, log it, or throw it again.

  3. Clean up Resources in finally: Always close resources (e.g., file streams, database connections) in the finally block to prevent resource leaks.

  4. Don’t Use Exceptions for Control Flow: Exceptions should be used to handle errors, not for regular control flow in the program.


9. Summary

By the end of Day 15, we will have a solid understanding of:

  • What exceptions are and why they are important in Java.

  • The types of exceptions (checked and unchecked) and how to handle them using try-catch.

  • How to use the throw and throws keywords to handle exceptions effectively.

  • The purpose and use of the finally block to ensure resource cleanup.

  • How to create custom exceptions to represent application-specific errors.

  • Best practices for clean, maintainable exception handling in Java applications.

Exception handling is crucial for building robust Java applications that can recover gracefully from runtime errors. Stay tuned! for further topics on Java.

10
Subscribe to my newsletter

Read articles from Mohit Upadhyay directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mohit  Upadhyay
Mohit Upadhyay