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
andNullPointerException
.
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