The Ultimate Guide to Exception Handling in Java — From Basics to Best Practices

Pushkar RoyPushkar Roy
6 min read

🧠 Introduction

No matter how perfect your Java code is, something can — and will — go wrong. Maybe it’s a missing file, a network glitch, or invalid input from the user. That’s where Java’s exception handling mechanism becomes best.

🔍 What is an Exception?

An exception in Java is an event that occurs during the execution of a program that disrupts the normal flow of instructions.

Exception = Unexpected runtime problem that can be caught and handled in code.

🔹 Common Types of Exceptions in Java

Here’s a list of frequently encountered exceptions in Java.


⚠️ NullPointerException

Occurs when you try to use an object reference that is null.

String text = null;
System.out.println(text.length());  // NullPointerException

⚠️ ArrayIndexOutOfBoundsException

Happens when accessing an invalid index in an array.

int[] nums = {1, 2, 3};
System.out.println(nums[5]);  // ArrayIndexOutOfBoundsException

⚠️ ArithmeticException

Thrown when illegal arithmetic operations occur (like division by zero).

int result = 10 / 0;  // ArithmeticException

⚠️ NumberFormatException

Thrown when trying to convert a string into a number, but the string isn’t numeric.

String s = "abc";
int num = Integer.parseInt(s);  // NumberFormatException

⚠️ ClassCastException

Occurs when trying to cast an object to a subclass it doesn’t belong to.

Object obj = new String("Hello");
Integer num = (Integer) obj;  // ClassCastException

⚠️ FileNotFoundException (Checked Exception)

Thrown when a file cannot be found at the specified path.

FileReader reader = new FileReader("missingfile.txt");  // FileNotFoundException

⚠️ IOException (Checked Exception)

General I/O failure like reading a file, closing a stream, etc.

BufferedReader br = new BufferedReader(new FileReader("file.txt"));

🔹 Types of Exceptions in Java

Java categorizes exceptions mainly into two types: Checked Exceptions and Unchecked Exceptions. This distinction helps developers know which exceptions must be handled explicitly and which ones are optional.


1. Checked Exceptions

These are exceptions that are checked at compile time. If your code contains a checked exception, the compiler will force you to handle it using a try-catch block or declare it using the throws keyword.

These exceptions usually relate to external factors such as:

  • File operations

  • Database access

  • Network connections

🔸 Example: FileNotFoundException

import java.io.*;

public class FileExample {
    public static void main(String[] args) {
        try {
            FileReader fr = new FileReader("data.txt");
        } catch (FileNotFoundException e) {
            System.out.println("File not found!");
        }
    }
}

🔹 Other Common Checked Exceptions:

  • IOException

  • SQLException

  • ParseException

  • InterruptedException


2. Unchecked Exceptions

These are exceptions that occur at runtime and are not checked during compilation. They typically result from programming errors such as:

  • Invalid logic

  • Bad input

  • Improper casting

  • Accessing null references

Unchecked exceptions are subclasses of RuntimeException.

🔸 Example: ArithmeticException

javaCopyEditpublic class DivideExample {
    public static void main(String[] args) {
        int result = 10 / 0;  // ArithmeticException
        System.out.println(result);
    }
}

🔹 Other Common Unchecked Exceptions:

  • NullPointerException

  • ArrayIndexOutOfBoundsException

  • NumberFormatException

  • ClassCastException

  • IllegalArgumentException


🔹 3. Exception Handling Mechanisms in Java

Java provides a systematic, object-oriented approach to mechanism to handle exceptions or runtime errors so that the program doesn't crash unexpectedly. This helps ensure stability and better user experience.

This section should cover the following key elements:


✅ 1. try-catch Block

Used to catch and handle exceptions. The risky code is placed inside the try, and handling logic is placed inside the catch.

public class TryCatchExample {
    public static void main(String[] args) {
        try {
            int number = 10 / 0;
        } catch (ArithmeticException e) {
            System.out.println("Cannot divide by zero!");
        }
    }
}

✅ 2. throw Keyword

Used to explicitly throw an exception from your code.

public class ThrowExample {
    public static void main(String[] args) {
        int age = 15;
        if (age < 18) {
            throw new IllegalArgumentException("Age must be 18 or older.");
        }
    }
}

✅ 3. Multiple Catch Blocks

You can catch different exception types with multiple catch blocks.

public class ThrowExample {
    public static void main(String[] args) {
try {
    String s = null;
    System.out.println(s.length());
} catch (NullPointerException e) {
    System.out.println("Null value found");
} catch (Exception e) {
    System.out.println("Some other error occurred");
}
}
}

✅ 4. finally Block

The finally block is always executed, regardless of whether an exception was thrown or not. It is commonly used to close resources like files, sockets, or database connections.

public class ThrowExample {
    public static void main(String[] args) {
try {
    int[] arr = new int[2];
    arr[3] = 5;
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("Index error!");
} finally {
    System.out.println("Cleanup done.");
}
}
}

🔹 Creating Custom Exceptions in Java

While Java provides many built-in exceptions, sometimes those aren't specific enough for your application’s needs. That’s where custom exceptions — you can define meaningful error messages and control how your application responds to specific business logic failures.


✅ Why Use Custom Exceptions?

  • To represent domain-specific errors

  • To make your code more readable and maintainable

  • To encapsulate logic around specific failure types (e.g., InsufficientBalanceException, InvalidInputException)


✅ How to Create a Custom Exception

Custom exceptions are created by extending the Exception or RuntimeException class.


🔸 a. Custom Checked Exception (extend Exception)

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

Usage:

public class VoterEligibility {
    public static void checkAge(int age) throws InvalidAgeException {
        if (age < 18) {
            throw new InvalidAgeException("Age must be 18 or above.");
        }
        System.out.println("Eligible to vote!");
    }

    public static void main(String[] args) {
        try {
            checkAge(16);
        } catch (InvalidAgeException e) {
            System.out.println("Custom Exception Caught: " + e.getMessage());
        }
    }
}

🔸 b. Custom Unchecked Exception (extend RuntimeException)

javaCopyEditpublic class InvalidAmountException extends RuntimeException {
    public InvalidAmountException(String message) {
        super(message);
    }
}

Usage:

public class PaymentService {
    public static void processPayment(int amount) {
        if (amount <= 0) {
            throw new InvalidAmountException("Amount must be greater than zero.");
        }
        System.out.println("Payment processed: " + amount);
    }

    public static void main(String[] args) {
        processPayment(0);  // Will throw custom unchecked exception
    }
}

Conclusion

Exception handling is one of the core pillars of building reliable, maintainable, and user-friendly Java applications. In this blog, we explored:

  • What exceptions are and why they occur

  • Common exceptions Java developers encounter

  • The difference between checked, unchecked, and error types

  • How to use try, catch, finally, throw, and throws effectively

  • How to create custom exceptions for specific business needs

Mastering these concepts will not only help you avoid crashes but also allow you to write more robust, readable, and resilient Java code.

Thank you for reading! 🙌

0
Subscribe to my newsletter

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

Written by

Pushkar Roy
Pushkar Roy

Hey 👋 I am Pushkar , I am learning person holding skills in Developing UI as well as backend using NodeJS and a passionate programmer who loves to code. I am creatively curious and a self-learner and self-motivated person who believes in smart work achieved from hard work . 🚀 Currently, my focus is on Full Stack Development, where I engage in daily practice of Data Structures and Algorithms and exploring web3 and new technologies. I’m also active in Open Source and looking forward to contributing to Open-Source Projects. ✨Proficient in Data Structures and Algorithms with a strong command of C++. 💻Front-end development expertise using ReactJS and NextJS with MySQL, ExpressJs ensuring the creation of fully responsive and scalable websites. 🌐Currently, I am focusing on JavaScript, TypeScript, NodeJS, React, NextJs and Data Structure. Let's connect if you share the love for coding, learning, and building cool things! 🤝