Contents

Exception

Exception in java

Exception Handling in Java is one of the effective means to manage runtime errors and preserve the regular flow of the application. Java’s mechanism for handling runtime errors like ClassNotFoundException, IOException, SQLException, and RemoteException ensures that exceptions are caught and handled appropriately.

What are Java Exceptions?

In Java, an Exception is an unwanted or unexpected event that occurs during the execution of a program, i.e., at runtime, which disrupts the normal flow of the program. Java provides mechanisms to catch and handle exceptions using the try-catch block. When an exception occurs, an exception object is created, containing information such as the name, description, and the program state at the time the exception occurred.

Major Reasons for Exceptions:
  • Invalid user input
  • Device failure
  • Loss of network connection
  • Out of disk memory
  • Code errors
  • Array index out of bounds
  • Null reference
  • Type mismatch
  • Attempt to open an unavailable file
  • Database errors
  • Arithmetic errors (e.g., division by zero)

Errors like memory leaks, stack overflow, and out of memory are irrecoverable conditions typically beyond the control of the programmer. Errors should not be handled.

Difference between Error and Exception:
  • Error: Represents a serious problem that the application should not attempt to catch.
  • Exception: Indicates a condition that a reasonable application might attempt to catch and handle.
Exception Hierarchy

In Java, all exceptions and errors are subclasses of the Throwable class. The two branches are:

  • Exception: User-defined and built-in exceptions such as NullPointerException.
  • Error: System-level errors like StackOverflowError, indicating issues with the JVM.
Types of Exceptions

1. Built-in Exceptions: Java has a wide range of built-in exceptions divided into two categories:

  • Checked Exceptions: These exceptions are checked at compile-time. Examples include IOException, SQLException.
  • Unchecked Exceptions: These exceptions occur at runtime and are not checked during compilation. Examples include ArrayIndexOutOfBoundsException and NullPointerException.

2. User-Defined Exceptions: When built-in exceptions do not adequately describe an issue, Java allows for the creation of custom exceptions.

Example of Exception Handling Methods:

1. printStackTrace() Prints the name, description, and stack trace of the exception.

				
					public class Main {
    public static void main(String[] args) {
        try {
            int a = 5;
            int b = 0;
            System.out.println(a / b);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
    }
}

				
			

Output:

				
					java.lang.ArithmeticException: / by zero
    at Main.main(Main.java:5)

				
			

2. toString() Prints the name and description of the exception.

				
					public class Main {
    public static void main(String[] args) {
        try {
            int a = 5;
            int b = 0;
            System.out.println(a / b);
        } catch (ArithmeticException e) {
            System.out.println(e.toString());
        }
    }
}

				
			

Output:

				
					java.lang.ArithmeticException: / by zero

				
			

3. getMessage() Prints only the description of the exception.

				
					public class Main {
    public static void main(String[] args) {
        try {
            int a = 5;
            int b = 0;
            System.out.println(a / b);
        } catch (ArithmeticException e) {
            System.out.println(e.getMessage());
        }
    }
}

				
			

Output:

				
					/ by zero
				
			
JVM Exception Handling Flow

When an exception occurs in a method, the method creates an Exception Object and passes it to the JVM. The JVM looks for an appropriate exception handler in the call stack, starting with the method where the exception occurred and moving backward. If no handler is found, the default exception handler terminates the program and prints the exception details.

Example of JVM Handling:

				
					public class Main {
    public static void main(String[] args) {
        String str = null;
        System.out.println(str.length()); // NullPointerException
    }
}

				
			

Output:

				
					Exception in thread "main" java.lang.NullPointerException
    at Main.main(Main.java:4)

				
			
Programmer Handling Exception with Custom Code:

Using try, catch, finally, throw, and throws, Java allows programmers to handle exceptions gracefully.

Example:

				
					public class Main {
    static int divideByZero(int a, int b) {
        return a / b;  // ArithmeticException if b is 0
    }

    static int computeDivision(int a, int b) {
        try {
            return divideByZero(a, b);
        } catch (NumberFormatException e) {
            System.out.println("NumberFormatException occurred");
            return 0;
        }
    }

    public static void main(String[] args) {
        try {
            int result = computeDivision(10, 0);
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }
}

				
			

Output:

				
					Error: / by zero

				
			

Try-Catch Clause Usage Example:

				
					public class Main {
    public static void main(String[] args) {
        int[] arr = new int[4];
        try {
            int value = arr[4]; // This will throw ArrayIndexOutOfBoundsException
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Array index is out of bounds.");
        }
        System.out.println("Program continues...");
    }
}

				
			

Output:

				
					Array index is out of bounds.
Program continues...

				
			

Types of Exception in Java

Built-in Exceptions in Java

Java has several pre-defined exceptions that relate to its standard library classes. These exceptions help explain certain error conditions and can be caught and handled. Below are some important built-in exceptions:

  • ArithmeticException: Thrown when an illegal arithmetic operation is performed, like division by zero.
  • ArrayIndexOutOfBoundsException: Occurs when attempting to access an array with an invalid index, either negative or beyond the array’s length.
  • ClassNotFoundException: Triggered when an application tries to load a class that cannot be found.
  • FileNotFoundException: Raised when attempting to access a file that does not exist or is unavailable.
  • IOException: Signals an issue with input-output operations, such as reading from a file.
  • InterruptedException: Happens when a thread is interrupted during sleep, waiting, or performing certain tasks.
  • NoSuchFieldException: Raised when trying to access a class field that does not exist.
  • NoSuchMethodException: Raised when attempting to invoke a method that doesn’t exist.
  • NullPointerException: Occurs when trying to call a method on an object reference that is null.
  • NumberFormatException: Thrown when trying to convert a string into a number but the string is not a valid number.
  • RuntimeException: Represents an error during program execution that is not checked at compile time.
  • StringIndexOutOfBoundsException: Thrown when attempting to access characters outside of a string’s bounds.
  • IllegalArgumentException: Raised when a method receives an inappropriate argument.
  • IllegalStateException: Triggered when a method is invoked at an illegal or inappropriate time.

Examples of Built-in Exceptions

  • ArithmeticException
				
					class ArithmeticExceptionExample {
    public static void main(String[] args) {
        try {
            int num1 = 50, num2 = 0;
            int result = num1 / num2;  // Cannot divide by zero
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Division by zero is not allowed.");
        }
    }
}

				
			

Output:

				
					Division by zero is not allowed.

				
			
  • NullPointerException
				
					class NullPointerExceptionExample {
    public static void main(String[] args) {
        try {
            String str = null;
            System.out.println(str.length()); // Null reference
        } catch (NullPointerException e) {
            System.out.println("Caught a NullPointerException.");
        }
    }
}

				
			

Output:

				
					Caught a NullPointerException.

				
			
  • StringIndexOutOfBoundsException
				
					class StringIndexOutOfBoundsExceptionExample {
    public static void main(String[] args) {
        try {
            String sample = "Java is fun"; // Length is 11
            char ch = sample.charAt(15);   // Accessing out of bounds
        } catch (StringIndexOutOfBoundsException e) {
            System.out.println("String index out of bounds.");
        }
    }
}

				
			

Output:

				
					String index out of bounds.

				
			
  • FileNotFoundException
				
					import java.io.*;

class FileNotFoundExceptionExample {
    public static void main(String[] args) {
        try {
            File file = new File("C://invalid_path.txt");
            FileReader reader = new FileReader(file);
        } catch (FileNotFoundException e) {
            System.out.println("The specified file is not found.");
        }
    }
}

				
			

Output:

				
					The specified file is not found.

				
			
  • NumberFormatException
				
					class NumberFormatExceptionExample {
    public static void main(String[] args) {
        try {
            int number = Integer.parseInt("abc123");  // Invalid number format
        } catch (NumberFormatException e) {
            System.out.println("Invalid format for a number.");
        }
    }
}

				
			

Output:

				
					Invalid format for a number.

				
			
  • ArrayIndexOutOfBoundsException
				
					class ArrayIndexOutOfBoundsExceptionExample {
    public static void main(String[] args) {
        try {
            int[] numbers = {1, 2, 3, 4, 5};
            System.out.println(numbers[6]);  // Invalid index access
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Array index is out of bounds.");
        }
    }
}

				
			

Output:

				
					Invalid format for a number.

				
			
  • ArrayIndexOutOfBoundsException
				
					class ArrayIndexOutOfBoundsExceptionExample {
    public static void main(String[] args) {
        try {
            int[] numbers = {1, 2, 3, 4, 5};
            System.out.println(numbers[6]);  // Invalid index access
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Array index is out of bounds.");
        }
    }
}

				
			

Output:

				
					Array index is out of bounds.

				
			
  • IOException
				
					import java.io.*;

class IOExceptionExample {
    public static void main(String[] args) {
        try {
            BufferedReader reader = new BufferedReader(new FileReader("nonexistentfile.txt"));
            String line = reader.readLine();
            System.out.println(line);
        } catch (IOException e) {
            System.out.println("Input-output error occurred.");
        }
    }
}

				
			

Output:

				
					Input-output error occurred.

				
			
User-Defined Exceptions

In addition to built-in exceptions, Java allows developers to create custom exceptions that describe unique error situations.

Steps:

1. Create a class extending Exception.
2. Write a constructor that passes a message to the Exception class.
3. Use throw to raise this custom exception in your program.

Example of User-Defined Exception

				
					class LowBalanceException extends Exception {
    LowBalanceException(String message) {
        super(message);
    }
}

class CustomExceptionExample {
    public static void main(String[] args) {
        double balance = 400.00;
        try {
            checkBalance(balance);
        } catch (LowBalanceException e) {
            System.out.println(e.getMessage());
        }
    }

    static void checkBalance(double balance) throws LowBalanceException {
        if (balance < 500) {
            throw new LowBalanceException("Balance is below the minimum threshold!");
        } else {
            System.out.println("Your balance is sufficient.");
        }
    }
}

				
			

Output:

				
					Balance is below the minimum threshold!

				
			

Checked vs Unchecked Exceptions in Java

In Java, an exception is an event that disrupts the normal flow of a program during its execution. Java categorizes exceptions into two types:

1. Checked Exceptions:

These exceptions are checked at compile time. If a method throws a checked exception, it must either handle the exception using a try-catch block or declare it using the throws keyword. Checked exceptions typically occur in scenarios that are beyond the control of the program, such as reading from a file or a network issue.

Example of a Checked Exception:

				
					import java.io.*;

public class CheckedExceptionDemo {
    public static void main(String[] args) throws IOException {
        // Trying to read from a non-existing file
        FileReader fileReader = new FileReader("D:\\data.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        
        // Reading the first three lines of the file
        for (int i = 0; i < 3; i++) {
            System.out.println(bufferedReader.readLine());
        }
        
        // Closing the file reader
        bufferedReader.close();
    }
}

				
			

Output:

				
					Exception in thread "main" java.io.FileNotFoundException: D:\data.txt (The system cannot find the file specified)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    ...

				
			
2. Unchecked Exceptions:

These exceptions are not checked at compile time. They are usually caused by programming errors like trying to access an array out of bounds or dividing by zero. Unchecked exceptions are derived from RuntimeException. Unlike checked exceptions, you are not required to handle or declare them in your method signature.

Example of an Unchecked Exception:

				
					public class UncheckedExceptionDemo {
    public static void main(String[] args) {
        // Dividing by zero will cause ArithmeticException
        int a = 5;
        int b = 0;
        int result = a / b;  // This will throw an exception
    }
}

				
			

Output:

				
					Exception in thread "main" java.lang.ArithmeticException: / by zero
    at UncheckedExceptionDemo.main(UncheckedExceptionDemo.java:5)

				
			

Here, ArithmeticException is an unchecked exception that occurs at runtime due to division by zero.

Other Examples of Checked and Unchecked Exceptions:

1. Checked Exception – Handling with throws:

				
					import java.io.*;

public class HandleCheckedException {
    public static void main(String[] args) throws IOException {
        FileReader reader = new FileReader("D:\\info.txt");
        BufferedReader bufferedReader = new BufferedReader(reader);

        System.out.println(bufferedReader.readLine());

        bufferedReader.close();
    }
}

				
			

Output:

				
					Exception in thread "main" java.io.FileNotFoundException: D:\info.txt (The system cannot find the file specified)

				
			

2. Unchecked Exception – NullPointerException:

				
					public class NullPointerExceptionDemo {
    public static void main(String[] args) {
        String data = null;
        System.out.println(data.length());  // This will cause a NullPointerException
    }
}

				
			

Output:

				
					Exception in thread "main" java.lang.NullPointerException
    at NullPointerExceptionDemo.main(NullPointerExceptionDemo.java:5)

				
			

3. Unchecked Exception – ArrayIndexOutOfBoundsException:

				
					public class ArrayIndexOutOfBoundsExceptionDemo {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3};
        System.out.println(numbers[5]);  // This will throw ArrayIndexOutOfBoundsException
    }
}

				
			

Output:

				
					Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
    at ArrayIndexOutOfBoundsExceptionDemo.main(ArrayIndexOutOfBoundsExceptionDemo.java:5)

				
			

Java Try Catch Block

In Java, an exception is an “undesirable or unexpected event” that occurs during the program’s execution, causing it to terminate unexpectedly. To prevent this abrupt termination, Java provides mechanisms like the try-catch block for handling exceptions. In this explanation, we will discuss the usage of try, catch, throw, throws, and finally in Java.

Reasons Why an Exception May Occur:

An exception can be triggered by multiple factors such as:

  • Issues with network connectivity
  • Incorrect input from the user
  • Attempting to open a file that doesn’t exist, etc.
Exception Handling Constructs and Keywords:

1. try Block : The try block encompasses the code that may potentially cause an exception. If an exception occurs in this block, it is transferred to the corresponding catch block.

				
					try {
    // code that might generate an exception
}

				
			

2. catch Block: The catch block handles exceptions thrown by the try block. It is always placed after the try block to process any exceptions that occur.

				
					catch (Exception e) {
    // code to handle the exception
    // e.g., closing resources, logging errors
}

				
			

3. throw Keyword: The throw keyword explicitly throws an exception, typically used to pass control from a try block to the catch block. It is often used when custom exceptions need to be raised.

Example:

				
					// Java program demonstrating the use of throw
class CustomExceptionExample {
    static void demonstrateThrow() {
        try {
            throw new IllegalArgumentException("Invalid argument");
        } catch (IllegalArgumentException e) {
            System.out.println("Caught in demonstrateThrow().");
            throw e;  // rethrowing the exception
        }
    }

    public static void main(String[] args) {
        try {
            demonstrateThrow();
        } catch (IllegalArgumentException e) {
            System.out.println("Caught in main with message:");
            System.out.println(e);
        }
    }
}

				
			

Output:

				
					Caught in demonstrateThrow().
Caught in main with message:
java.lang.IllegalArgumentException: Invalid argument

				
			

4. throws Keyword: The throws keyword is used to declare exceptions in a method signature without handling them within the method itself. This allows the calling method to handle the exception instead.

Example:

				
					// Java program demonstrating throws
class ThrowsDemo {
    // This method declares an exception
    static void riskyMethod() throws IllegalStateException {
        System.out.println("Inside riskyMethod.");
        throw new IllegalStateException("Critical error");
    }

    public static void main(String[] args) {
        try {
            riskyMethod();
        } catch (IllegalStateException e) {
            System.out.println("Caught in main.");
        }
    }
}

				
			

Output:

				
					Inside riskyMethod.
Caught in main.

				
			

5. finally Block: The finally block is always executed after the try-catch blocks, regardless of whether an exception was thrown or not. It is typically used for code that needs to execute no matter what, such as closing resources.

Example:

				
					// Java program demonstrating try, catch, and finally
class FinalBlockExample {
    public static void main(String[] args) {
        int num1 = 20, num2 = 10, num3 = 10, result;
        
        try {
            result = num1 / (num2 - num3);  // Will cause division by zero
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Exception caught: Division by zero");
        } finally {
            System.out.println("This is the finally block.");
        }
    }
}

				
			

Output:

				
					Exception caught: Division by zero
This is the finally block.

				
			

Flow control in try catch finally in Java

In this article, we will explore all the possible combinations of try-catch-finally blocks and how control flow behaves when an exception is thrown. We’ll cover different cases that can arise, such as exceptions being caught, not caught, and cases where no exception occurs.

Control Flow in try-catch or try-catch-finally Blocks:

Exception Occurs in try Block and Is Handled in catch Block

When an exception occurs in the try block, the remaining code in that block will not be executed. The control is passed to the corresponding catch block, where the exception is handled. After the catch block, if a finally block exists, it will execute, and then the rest of the program will continue.

Control Flow Example with try-catch:

				
					// Java program to demonstrate control flow
// when an exception occurs in the try block
// and is handled in the catch block
class Example1 {
    public static void main(String[] args) {
        int[] arr = new int[4];
        try {
            int i = arr[4];  // Exception occurs here
            System.out.println("Inside try block");
        } catch (ArrayIndexOutOfBoundsException ex) {
            System.out.println("Exception caught in catch block");
        }
        System.out.println("Outside try-catch block");
    }
}

				
			

Output:

				
					Exception caught in catch block
Outside try-catch block

				
			

Control Flow Example with try-catch-finally:

				
					// Java program to demonstrate control flow
// with try-catch-finally when an exception occurs
class Example2 {
    public static void main(String[] args) {
        int[] arr = new int[4];
        try {
            int i = arr[4];  // Exception occurs here
            System.out.println("Inside try block");
        } catch (ArrayIndexOutOfBoundsException ex) {
            System.out.println("Exception caught in catch block");
        } finally {
            System.out.println("finally block executed");
        }
        System.out.println("Outside try-catch-finally block");
    }
}

				
			

Output:

				
					Exception caught in catch block
finally block executed
Outside try-catch-finally block

				
			

Control Flow in try-finally:

In the try-finally block, the finally block always executes, regardless of whether an exception occurs or not. The control flow differs depending on whether an exception is raised.

Exception Occurs in try Block

				
					// Java program to demonstrate control flow
// when an exception occurs in try-finally block
class Example7 {
    public static void main(String[] args) {
        int[] arr = new int[4];
        try {
            int i = arr[4];  // Exception occurs here
            System.out.println("Inside try block");
        } finally {
            System.out.println("finally block executed");
        }
        System.out.println("Outside try-finally block");
    }
}

				
			

Output:

				
					finally block executed
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4

				
			

throw and throws in Java

In Java, exception handling is a crucial mechanism to manage runtime errors, ensuring that the normal flow of a program isn’t interrupted. Common exceptions include ClassNotFoundException, IOException, SQLException, and RemoteException, among others.

This article will delve into two essential components of exception handling in Java: the throw and throws keywords, explaining their use and providing practical examples.

Java throw

The throw keyword is used to explicitly raise an exception from a method or block of code. Both checked and unchecked exceptions can be thrown using throw, and it is especially useful for raising custom exceptions.

Syntax:

				
					throw instance;

				
			

Where instance is an object of type Throwable or its subclass. For example, Exception is a subclass of Throwable, and user-defined exceptions generally extend the Exception class. Unlike languages like C++, Java does not allow basic data types (like int or char) or non-throwable classes to be used as exceptions.

When a throw statement is executed, the program’s control flow is immediately transferred to the nearest enclosing try-catch block that can handle the exception. If no matching catch block is found, the program terminates with an error.

Java throw Examples
Example 1:

				
					// Java program to demonstrate the use of throw
class CustomThrowExample {
    static void checkException() {
        try {
            throw new IllegalArgumentException("Demo Exception");
        } catch (IllegalArgumentException e) {
            System.out.println("Caught inside checkException().");
            throw e;  // rethrowing the exception
        }
    }

    public static void main(String[] args) {
        try {
            checkException();
        } catch (IllegalArgumentException e) {
            System.out.println("Caught in main.");
        }
    }
}

				
			

Output:

				
					Caught inside checkException().
Caught in main.

				
			

User-defined Custom Exception

In Java, an exception is a runtime issue that interrupts the normal execution flow of a program. When an exception occurs, the program is terminated unexpectedly, and any code following the exception-generating statement is not executed.

Java allows developers to create their own exceptions, which are subclasses of the Exception class. This is referred to as a custom exception or user-defined exception. Custom exceptions are primarily used to suit specific requirements by adding custom error-handling logic.

For instance, in the following example, the class CustomException extends the Exception class to create a new custom exception.

Why Use Custom Exceptions?

While Java provides a wide range of built-in exceptions, there are scenarios where custom exceptions are beneficial. Below are some reasons for creating custom exceptions:

1.Specific Exception Handling: Custom exceptions can target a specific subset of existing exceptions, allowing more refined exception handling.
Business Logic Exceptions: Custom exceptions are useful for handling business logic errors, making it easier for developers and users to understand the nature of the problem in the workflow.

To define a custom exception, you need to extend the Exception class, which is part of the java.lang package.

Example:

				
					// A class representing a user-defined exception
class CustomException extends Exception {
    public CustomException(String message) {
        // Call the constructor of the parent Exception class
        super(message);
    }
}

// A class that uses the CustomException
public class MainApp {
    // Main method
    public static void main(String[] args) {
        try {
            // Throw an instance of the custom exception
            throw new CustomException("Custom exception occurred");
        } catch (CustomException e) {
            System.out.println("Exception caught");

            // Print the message from the CustomException object
            System.out.println(e.getMessage());
        }
    }
}

				
			

Output:

				
					Exception caught
Custom exception occurred

				
			

Chained Exceptions in Java

Chained Exceptions in Java allow developers to associate one exception with another, establishing a relationship between them. This is helpful when one exception is a direct result of another. For instance, imagine a scenario where a method throws an ArithmeticException due to division by zero, but the real cause was an I/O error that led to the divisor being zero. In such a case, only the ArithmeticException would be reported, making it difficult for the caller to understand the root cause. Chained Exceptions solve this problem by allowing the original exception to be linked with the final exception.

Constructors in the Throwable Class Supporting Chained Exceptions:

1.Throwable(Throwable cause): Accepts the cause of the current exception as an argument.

2. Throwable(String msg, Throwable cause):Takes a custom error message (msg) and the cause (cause) as arguments.

Methods in the Throwable Class Supporting Chained Exceptions:

1. getCause():Retrieves the original cause of the exception.

2. initCause(Throwable cause):Allows setting the cause for the current exception.

Example of Chained Exception Usage:

				
					// Java program demonstrating chained exceptions
public class ChainedExceptionDemo {
    public static void main(String[] args) {
        try {
            // Create a new ArithmeticException
            ArithmeticException ex = new ArithmeticException("Arithmetic error occurred");

            // Set the cause of this exception to an I/O-related issue
            ex.initCause(new IllegalStateException("Caused by a file error"));

            // Throw the exception
            throw ex;
        } catch (ArithmeticException ex) {
            // Display the exception message
            System.out.println(ex);

            // Retrieve and display the actual cause of the exception
            System.out.println("Caused by: " + ex.getCause());
        }
    }
}

				
			

Output:

				
					java.lang.ArithmeticException: Arithmetic error occurred
Caused by: java.lang.IllegalStateException: Caused by a file error

				
			
				
					finally block executed
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4