Exception Handling in Java is a valuable approach for managing runtime errors and ensuring the smooth execution of an application. It involves handling various runtime errors such as ClassNotFoundException, IOException, SQLException, RemoteException, and others.
An exception refers to an unexpected or undesired occurrence that prevents a programme from running normally during its execution. These exceptions can be caught and managed within the program. When an exception occurs within a method, it gives rise to an object known as the exception object. This object contains pertinent information about the exception, including its name, description, and the program’s state at the time of the exception occurrence.
Join FITA academy‘s Java training in Chennai and start your journey to becoming a pro!
Major reasons why an Exception Occurs
There are several scenarios that can lead to errors in a program:
- Invalid user input: When a user provides incorrect or unexpected input, it can result in errors during program execution.
- Device failure: Errors can occur if there is a failure or malfunction of a hardware device on which the program relies.
- Loss of network connection: When a program depends on network connectivity, errors may arise if the connection is lost or disrupted.
- Physical limitations (out of disk memory): If a program exhausts the available disk memory, it can lead to errors and affect its proper functioning.
- Code errors: Mistakes or bugs in the program’s code can cause errors during runtime.
- Opening an unavailable file: If a program attempts to access a file that is unavailable or inaccessible, it can result in errors.
Errors represent conditions that are usually beyond the programmer’s control and are considered irrecoverable. Examples of such errors include the Running out of memory, memory leaks, stack overflow issues, library incompatibility, and infinite recursion are all problems with the Java virtual machine (JVM). It is generally not advisable to handle these types of errors in the program.
Distinguishing between Errors and Exceptions is crucial. Here are the key differences:
Error: An Error signifies a severe issue that it is generally not advisable for an application to attempt to handle or catch.
Exception: Exception denotes situations where it is reasonable for an application to try catching and handling the exceptional condition.
Exception Hierarchy
In the class hierarchy of Java, all exception and error types are derived from the base class Throwable. The hierarchy branches into two categories. The first branch is led by the Exception class, which is utilized for exceptional conditions that should be caught by user programs. For instance, NullPointerException is an example of such an exception.
The second branch consists of the Error class, which is employed by the Java run-time system (JVM) to indicate errors related to the runtime environment itself (JRE). An example of such an error is StackOverflowError.
Types of Exceptionsย
Java provides various types of exceptions that are related to its class libraries, and it also allows users to create their own exceptions.
Exceptions can be classified into two categories:
A. Built-in Exceptions
Built-in exceptions are exceptions that are already defined in Java libraries. These exceptions are designed to handle specific error situations.
Checked Exceptions: Checked exceptions are referred to as compile-time exceptions because they are checked by the compiler during compilation.
Unchecked Exceptions: On the other hand, unchecked exceptions are not checked by the compiler at compile time. If a program throws an unchecked exception and it is not handled or declared, the program will not generate a compilation error.
B. User-Defined Exceptions:
In certain cases, the built-in exceptions in Java may not be suitable to describe a specific situation. In such scenarios, users can create their own exceptions, known as “user-defined exceptions.”
Advantages of Exception Handling in Javaย
- Ensuring completion of program execution.
- Facilitating easy identification of program code and error-handling code.
- Propagating errors in a controlled manner.
- Enabling meaningful error reporting.
- Identifying different types of errors.
Learn Java training in Bangalore from One of the most recognised training centres in Bangalore
There are several ways to display exception information:
- Using the `printStackTrace()` method: This method prints the exception information in a specific format that includes the name of the exception, a description of the exception, and the stack trace.
//program to print the exception information using printStackTrace() method
import java.io.*;
class GFG {
public static void main (String[] args) {
int a=5;
int b=0;
try{
System.out.println(a/b);
}
catch(ArithmeticException e){
e.printStackTrace();
}
}
}
Output:
java.lang.ArithmeticException: / by zero
at GFG.main(File.java:10)
- Utilizing the `toString()` method: With this approach, the exception information is displayed in a format that includes the name of the exception and a description of the exception without the stack trace.
//program to print the exception information using toString() method
import java.io.*;
class GFG1 {
public static void main (String[] args) {
int a=5;
int b=0;
try{
System.out.println(a/b);
}
catch(ArithmeticException e){
System.out.println(e.toString());
}
}
}
Output:
java.lang.ArithmeticException: / by zero
- Employing the `getMessage()` method: This method allows you to print only the description of the exception, omitting the stack trace and other details.
//program to print the exception information using getMessage() method
import java.io.*;
class GFG1 {
public static void main (String[] args) {
int a=5;
int b=0;
try{
System.out.println(a/b);
}
catch(ArithmeticException e){
System.out.println(e.getMessage());
}
}
}
Output:
/ by zero
If you want to design your own application, there are many resources available online, including tutorials. You may also check out Java Tutorial for learning about Java.
How Does JVM Handle an Exception?
In default exception handling, when an exception occurs with an exception object is created within a method. and passed to the runtime system (JVM). This Exception Object contains the exception’s name, description, and the current state of the program at the point of occurrence. The steps involved in creating the Exception Object and transferring it to the runtime system is known as throwing an exception. The call stack is a sequential list of methods that have been invoked leading up to the method where the exception was encountered.
During exception handling, the runtime system scans the call stack in reverse order, starting from the method where the exception originated. It searches for a method that contains a code block capable of handling the specific exception. This code block is referred to as an exception handler. If an appropriate handler is found, the exception is passed to it for handling.
However, if the runtime system exhaustively traverses the entire call stack without locating a suitable exception handler, the Exception Object is handed over to the default exception handler, which is an integral part of the runtime system. This default handler prints the exception information in a specific format and abruptly terminates the program
To comprehend how the call stack flows, look at the diagram below.
Illustration
// Java Program to Demonstrate How Exception Is Thrown
// Class
// ThrowsExecp
class GFG {
// Main driver method
public static void main(String args[])
{
// Taking an empty string
String str = null;
// Getting length of a string
System.out.println(str.length());
}
}
Output:
Let’s look at an example that demonstrates how a run-time system examines the call stack for appropriate exception handling code.
// Java Program to Demonstrate Exception is Thrown
// How the runTime System Searches Call-Stack
// to Find Appropriate Exception Handler
// Class
// ExceptionThrown
class GFG {
// Method 1
// It throws the Exception(ArithmeticException).
// Appropriate Exception handler is not found
// within this method.
static int divideByZero(int a, int b)
{
// this statement will cause ArithmeticException
// (/by zero)
int i = a / b;
return i;
}
// The runTime System searches the appropriate
// Exception handler in method also but couldn't have
// found. So looking forward on the call stack
static int computeDivision(int a, int b)
{
int res = 0;
// Try block to check for exceptions
try {
res = divideByZero(a, b);
}
// Catch block to handle NumberFormatException
// exception Doesn't matches with
// ArithmeticException
catch (NumberFormatException ex) {
// Display message when exception occurs
System.out.println(
"NumberFormatException is occurred");
}
return res;
}
// Method 2
// Found appropriate Exception handler.
// i.e. matching catch block.
public static void main(String args[])
{
int a = 1;
int b = 0;
// Try block to check for exceptions
try {
int i = computeDivision(a, b);
}
// Catch block to handle ArithmeticException
// exceptions
catch (ArithmeticException ex) {
// getMessage() will print description
// of exception(here / by zero)
System.out.println(ex.getMessage());
}
}
}
Output
/ by zero
Learn Java training in Pune from One of the most recognised training centres in Pune
How do Programmers Handle an Exception?
In Java, customized exception handling is facilitated through the usage of five essential keywords: try, catch, throw, throws, and finally. Here’s a brief overview of their functionality.
The try block is used to enclose program statements that are prone to raise exceptions. The exception is thrown if it happens within the try block. To handle such exceptions, your code can catch them using a catch block and provide appropriate handling mechanisms. The Java run-time system itself generates system-defined exceptions. However, you can manually throw an exception using the throw keyword when needed.
When an exception is thrown out of a method, it must be declared using the throws clause to specify the exceptional scenarios that can occur. This ensures proper handling of the exception by the caller of the method.
Finally, the final block is utilised to include code that must be executed regardless of whether an exception occurs or not. It guarantees the execution of critical code that must be run once the try block has been completed.
Try-catch clause (customised exception handling) is required.
To further understand the try-catch clause, take a look at the programme below.
Example:
// Java Program to Demonstrate
// Need of try-catch Clause
// Class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Taking an array of size 4
int[] arr = new int[4];
// Now this statement will cause an exception
int i = arr[4];
// This statement will never execute
// as above we caught with an exception
System.out.println("Hi, I want to execute");
}
}
Output:ย
output justification
In the aforementioned example, an array is constructed with a size, and the only indexes that can access its elements are 0 and 3. However, the reason it is raising an exception is because you are mistakenly attempting to access the components at index 4. JVM terminates the programme abnormally in this situation. System.out.println(“Hi, I want to execute”); will never actually take effect. We must use try-catch to handle the exception in order to execute it. Hence, a try-catch clause is required in order to maintain the program’s usual flow.
How to Use the try-catch Clause?
attempt {
// code block to monitor for errors
// the code that may potentially raise an exception
} catch (ExceptionType1 exObj) {
// exception handler for ExceptionType1
} catch (ExceptionType2 exObj) {
// exception handler for ExceptionType2
}
// optional
finally { // code block to be executed after the attempt block ends
}
Join FITA academy’s Java training in Marathahalliย and start your journey to becoming a pro!
Here are some important points to remember regarding exception handling
- To handle multiple statements that may throw exceptions within a method, place each statement in its own try block and provide a separate catch block for each of them.
- If an exception occurs within a try block, it is handled by the corresponding catch block associated with that try block. To handle various error kinds, multiple catch blocks can be utilised. Each catch block specifies the exception type it can handle, which must be a class inheriting from the Throwable class.
- A try block can have No catch blocks or more, but just one final block.
- The finally block is optional but important. It always gets executed, regardless of whether an exception occurred in the try block or not. After the try block, the finally block is invoked if an exception arises and catch blocks. If no exception occurs, it is executed after the try block. The finally block is typically used for crucial tasks like cleaning up resources, such as closing files or connections.
- If a System.exit statement is present within the try block, the finally block will not be executed.
Remember these key points while working with exception handling in Java.