Exception Handling in Java
The Exception Handling in Java is one of the powerful mechanism to handle the runtime errors so
that the normal flow of the application can be maintained.
In Java, an exception is an event that occurs during the execution of a program that disrupts the normal
flow of instructions. These exceptions can occur for various reasons, such as invalid user input, file not
found, or division by zero. When an exception occurs, it is typically represented by an object of a
subclass of the java.lang.Exception class.
What is Exception Handling?
Exception Handling is a mechanism to handle runtime errors such as ClassNotFoundException,
IOException, SQLException, RemoteException, etc.
Hierarchy of Java Exception classes
The java.lang.Throwable class is the root class of Java Exception hierarchy inherited by two
subclasses: Exception and Error. The hierarchy of Java Exception classes is given below:
Types of Java Exceptions
In Java, exceptions are categorized into two main types: checked exceptions and unchecked
exceptions. Additionally, there is a third category known as errors. Let's delve into each of these types:
1. Checked Exception
2. Unchecked Exception
3. Error
1
1. Checked Exceptions
Checked exceptions are the exceptions that are checked at compile-time. This means that the compiler
verifies that the code handles these exceptions either by catching them or declaring them in the method
signature using the throws keyword. Examples of checked exceptions include:
IOException: An exception is thrown when an input/output operation fails, such as when
reading from or writing to a file.
SQLException: It is thrown when an error occurs while accessing a database.
ParseException: Indicates a problem while parsing a string into another data type, such as
parsing a date.
ClassNotFoundException: It is thrown when an application tries to load a class through its
string name using methods like Class.forName(), but the class with the specified name cannot
be found in the classpath.
2. Unchecked Exceptions (Runtime Exceptions)
Unchecked exceptions, also known as runtime exceptions, are not checked at compile-time. These
exceptions usually occur due to programming errors, such as logic errors or incorrect assumptions in
the code. They do not need to be declared in the method signature using the throws keyword, making it
optional to handle them. Examples of unchecked exceptions include:
NullPointerException: It is thrown when trying to access or call a method on an object
reference that is null.
ArrayIndexOutOfBoundsException: It occurs when we try to access an array element with
an invalid index.
ArithmeticException: It is thrown when an arithmetic operation fails, such as division by zero.
IllegalArgumentException: It indicates that a method has been passed an illegal or
inappropriate argument.
3. Errors
Errors represent exceptional conditions that are not expected to be caught under normal circumstances.
They are typically caused by issues outside the control of the application, such as system failures or
resource exhaustion. Errors are not meant to be caught or handled by application code. Examples of
errors include:
OutOfMemoryError: It occurs when the Java Virtual Machine (JVM) cannot allocate enough
memory for the application.
StackOverflowError: It is thrown when the stack memory is exhausted due to excessive
recursion.
NoClassDefFoundError: It indicates that the JVM cannot find the definition of a class that
was available at compile-time.
Understanding the different types of exceptions in Java is crucial for writing robust and reliable
code. By handling exceptions appropriately, you can improve the resilience of your
applications and provide better user experiences.hierarchy of exception handling
Java Exception Keywords
Try : The "try" keyword is used to specify a block where we should place an exception code.
Catch : The "catch" block is used to handle the exception. It must be preceded by try block
which means we can't use catch block alone. It can be followed by finally block later.
Finally: The "finally" block is used to execute the necessary code of the program. It is executed
whether an exception is handled or not.
Throw:The "throw" keyword is used to throw an exception.
Throws: The "throws" keyword is used to declare exceptions. It specifies that there may occur
an exception in the method. It doesn't throw an exception. It is always used with method
signature.
2
Java Exception Handling Example
//Java Program to understand the use of exception handling in Java
public class Main{
public static void main(String args[]){
try{
//code that may raise exception
int data=100/0;
}catch(ArithmeticException e){System.out.println(e);}
//rest code of the program
System.out.println("rest of the code...");
}
}
Compile and Run
Output:
Exception in thread main java.lang.ArithmeticException:/ by zero
rest of the code...
In the above example, 100/0 raises an ArithmeticException which is handled by a try-catch block.
Handling Multiple Exceptions
You can handle multiple types of exceptions by providing multiple catch blocks, each catching a
different type of exception. This allows you to tailor your exception handling logic based on the
specific type of exception thrown. Here's an example:
try {
// Code that may throw an exception
} catch (IOException e) {
// Handle IOException
} catch (NumberFormatException e) {
// Handle NumberFormatException
} catch (Exception e) {
// Handle any other exceptions
}
The finally Block
In addition to try and catch, Java also provides a finally block, which allows you to execute cleanup
code, such as closing resources, regardless of whether an exception occurs or not. The finally block is
typically used to release resources that were acquired in the try block. Here's an example:
try {
// Code that may throw an exception
} catch (Exception e) {
// Exception handling code
} finally {
// Cleanup code
}
Common Scenarios of Java Exceptions
There are given some scenarios where unchecked exceptions may occur. They are as follows:
1) A scenario where ArithmeticException occurs
If we divide any number by zero, there occurs an ArithmeticException.
1. int a=50/0;//ArithmeticException
Here's a simple Java code example where an ArithmeticException occurs:
3
Example
//Java Program to illustrate the use of Arithmetic Exception in Java
public class Main {
public static void main(String[] args) {
int dividend = 10;
int divisor = 0;
try {
int result = dividend / divisor; // Division by zero
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Error: Division by zero is not allowed.");
// Additional error handling code can be added here
}
}
}
Compile and Run
Output:
Error: Division by zero is not allowed.
2) A scenario where NullPointerException occurs
If we have a null value in any variable, performing any operation on the variable throws a
NullPointerException.
String s=null;
System.out.println(s.length());//NullPointerException
Here's a Java code example where a NullPointerException occurs:
Example
//Java Program to illustrate the use of Null Pointer Exception in Java
public class Main {
public static void main(String[] args) {
String str = null; // Initializing a String variable to null
try {
int length = str.length(); // Attempting to call a method on a null reference
System.out.println("Length of the string: " + length);
} catch (NullPointerException e) {
System.out.println("Error: Null reference encountered.");
// Additional error handling code can be added here
}
}
}
Compile and Run
Output:
Error: Null reference encountered.
3) A scenario where NumberFormatException occurs
If the formatting of any variable or number is mismatched, it may result into NumberFormatException.
Suppose we have a string variable that has characters; converting this variable into digit will cause
NumberFormatException.
1. String s="abc";
2. int i=Integer.parseInt(s);//NumberFormatException
Here's a Java code example where a NumberFormatException occurs:
4
Example
//Java Program to illustrate the use of Number Format Exception in Java
public class Main {
public static void main(String[] args) {
String str = "abc"; // Initializing a String with non-numeric characters
try {
int num = Integer.parseInt(str); // Attempting to parse a non-numeric string to an intege
r
System.out.println("Parsed number: " + num);
} catch (NumberFormatException e) {
System.out.println("Error: Unable to parse the string as an integer.");
// Additional error handling code can be added here
}
}
}
Compile and Run
Output:
Error: Unable to parse the string as an integer.
4) A scenario where ArrayIndexOutOfBoundsException occurs
When an array exceeds to it's size, the ArrayIndexOutOfBoundsException occurs. there may be other
reasons to occur ArrayIndexOutOfBoundsException. Consider the following statements.
int a[]=new int[5];
a[10]=50; //ArrayIndexOutOfBoundsException
Here's a Java code example where an ArrayIndexOutOfBoundsException occurs:
Example
//Java Program to illustrate the use of ArrayIndexOutOfBoundsException in Java
public class Main {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5}; // Initializing an array with 5 elements
try {
int index = 10; // Accessing an index that is out of bounds
int value = numbers[index]; // Attempting to access an element at an invalid ind
ex
System.out.println("Value at index " + index + ": " + value);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Error: Index is out of bounds.");
// Additional error handling code can be added here
}
}
}
Compile and Run
Output:
Error: Index is out of bounds.
Best Practices for Exception Handling
Catch Specific Exceptions: Catch specific exceptions whenever possible rather than catching general
Exception objects. It helps in providing more precise error handling and makes your code easier to
understand and maintain.
5
Keep Exception Handling Simple: Avoid overly complex exception handling logic. Keep your catch
blocks concise and focused on handling the specific exception they are designed for. Complex
exception handling logic can make your code difficult to debug and maintain.
Log Exceptions: Always log exceptions or error messages when handling them. This helps in
troubleshooting issues and diagnosing problems in production environments.
Throw Exceptions Appropriately: Throw exceptions when necessary, but avoid excessive use of
checked exceptions. Checked exceptions should be used for exceptional conditions that the caller can
reasonably be expected to handle.
Use Custom Exceptions: Create custom exception classes for specific error conditions in your
application. This helps in providing meaningful error messages and makes your code more self-
documenting.
Example -throws
Throw an exception if age is below 18 (print "Access denied"). If age is 18 or older, print "Access
granted":
public class Main {
static void checkAge(int age) throws ArithmeticException {
if (age < 18) {
throw new ArithmeticException("Access denied - You must be at least 18 years old.");
}
else {
System.out.println("Access granted - You are old enough!");
}
}
public static void main(String[] args) {
checkAge(15); // Set age to 15 (which is below 18...)
}
}
Example-2
private static List <Integer> integers = new ArrayList <Integer>();
public static void addInteger(Integer value) throws IllegalArgumentException {
if (integers.contains(value)) {
throw new IllegalArgumentException("Integer already added.");
}
integers.add(value);
}
public static void main(String[] args) {
try {
addInteger(1);
} catch (IllegalArgumentException iae) {
iae.printStackTrace();
}
}
6
In this example, the “addInteger” method throws an IllegalArgumentException using the throw
keyword in case the “integers” ArrayList object already contains the integer passed.
Since IllegalArgumentException is a checked exception, it must be handled within the “addInteger”
method or its caller. In this example, the “addInteger” method does not handle the exception and
throws it to the caller using the throws keyword.
Therefore the caller, “main”, has to handle the IllegalArgumentException using a try-catch block.
Throw Throws
Used within a method (or constructor) Used with method (or constructor) signature
Used to throw an exception explicitly Used to declare exceptions
Can only throw a single exception Can declare multiple exceptions
Followed by a throwable instance Followed by an exception class name
Cannot be used to propagate checked Can be used to propagate checked exceptions by
Exception by itself itself