Exception Handling
Exception Handling
EXCEPTIONS
Java Exceptions
• Device failure
• Code errors
• Errors represent irrecoverable conditions such as Java virtual machine (JVM) running out of
memory, memory leaks, stack overflow errors, library incompatibility, infinite recursion, etc.
• Errors are usually beyond the control of the programmer and we should not try to handle errors.
Exceptions
2) Unchecked Exception
The classes which inherit RuntimeException are known as unchecked
exceptions.
e.g. ArithmeticException, NullPointerException,
ArrayIndexOutOfBoundsException etc.
Unchecked exceptions are not checked at compile-time, but they are checked
at runtime.
Java Exception hierarchy
• As you can see from the
image, the Throwable class
is the root class in the
hierarchy.
• A runtime exception happens due to a programming error. They are also known as
unchecked exceptions.
• These exceptions are not checked at compile-time but run-time. Some of the common
runtime exceptions are:
o Improper use of an API - IllegalArgumentException
o Null pointer access (missing the initialization of a variable) - NullPointerException
o Out-of-bounds array access - ArrayIndexOutOfBoundsException
o Dividing a number by 0 - ArithmeticException
1. RuntimeException
• You can think about it in this way. “If it is a runtime exception, it is your fault”.
• The NullPointerException would not have occurred if you had checked whether the variable was
initialized or not before using it.
• An ArrayIndexOutOfBoundsException would not have occurred if you tested the array index
against the array bounds.
Some scenarios where unchecked exceptions may occur:
int a=50/0;//ArithmeticException
String s=null;
System.out.println(s.length());//NullPointerException
3) A scenario where NumberFormatException occurs
The wrong formatting of any value may occur NumberFormatException.
Suppose I have a string variable that has characters, converting this variable
into digit will occur NumberFormatException.
String s="abc";
int i=Integer.parseInt(s);//NumberFormatException
• An IOException is also known as a checked exception. They are checked by the compiler at the
compile-time and the programmer is prompted to handle these exceptions.
• In Java, we use the exception handler components try, catch and finally blocks to handle
exceptions.
• To catch and handle an exception, we place the try...catch...finally block around the code that
might generate an exception. The finally block is optional.
• The syntax for try...catch...finally is:
try {
// code
} catch (ExceptionType e) {
// catch block
} finally {
// finally block
}
Java try...catch block
• The code that might generate an exception is placed in the try block.
• Every try block should be immediately followed by the catch or finally block. When an exception
occurs, it is caught by the catch block that immediately follows it.
• catch blocks cannot be used alone and must always be preceded by a try block.
Example 1: try...catch blocks
class Main {
public static void main(String[] args) {
try {
int divideByZero = 5 / 0;
System.out.println("Rest of code in try block");
} catch (ArithmeticException e) {
System.out.println("ArithmeticException => " + e.getMessage());
}
}
}
Output
• We have divided a number by 0 inside the try block. This produces an ArithmeticException.
• When the exception occurs, the program skips the rest of the code in the try block.
• Here, we have created a catch block to handle ArithmeticException. Hence, the statements inside
the catch block are executed.
If none of the statements in the try block generates an exception, the catch block is skipped.
Multiple Catch blocks
For each try block, there can be zero or more catch blocks.
The argument type of each catch block indicates the type of exception that can be handled by it.
Multiple catch blocks allow us to handle each exception differently.
Example 2: Multiple catch blocks
class ListOfNumbers {
public int[] arrayOfNumbers = new int[10];
try {
arrayOfNumbers[10] = 11;
} catch (NumberFormatException e1) {
System.out.println("NumberFormatException => " + e1.getMessage());
} catch (IndexOutOfBoundsException e2) {
System.out.println("IndexOutOfBoundsException => " + e2.getMessage());
}
}
} Output
class Main {
public static void main(String[] args) {
IndexOutOfBoundsException => Index 10 out of
ListOfNumbers list = new ListOfNumbers(); bounds for length 10
list.writeList();
}
}
In this example, we have declared an array of integers arrayOfNumbers of size 10.
We know that an array index always starts from 0. So, when we try to assign a value to index 10, an
IndexOutOfBoundsException occurs because the array bounds for arrayOfNumbers is 0 to 9.
o The exception is thrown to the first catch block. The first catch block does not handle an
IndexOutOfBoundsException, so it is passed to the next catch block.
o The second catch block in the above example is the appropriate exception handler because it
handles an IndexOutOfBoundsException. Hence, it is executed.
Java finally block
For each try block, there can be only one finally block.
The finally block is optional. However, if defined, it is always executed (even if the exception doesn't
occur).
If an exception occurs, it is executed after the try...catch block. If no exception occurs, it is executed
after the try block.
Java finally block
The basic syntax of finally block is:
try {
//code
} catch (ExceptionType1 e1) {
// catch block
} catch (ExceptionType1 e2) {
// catch block
} finally {
// finally block always executes
}
Example 3: finally block
class Main {
public static void main(String[] args) {
try {
int divideByZero = 5 / 0;
} catch (ArithmeticException e) {
System.out.println("ArithmeticException => " + e.getMessage());
} finally {
Output
System.out.println("Finally block is always executed");
} ArithmeticException => / by
}
zero
Finally block is always
} executed
In this example, we have divided a number by 0. This throws an ArithmeticException which is
caught by the catch block. The finally block always executes.
Having a finally block is considered a good practice. It is because it includes important cleanup code
such as:
o code that might have been accidentally skipped by return, continue or break statements
o closing a file or connection
We have mentioned that finally always executes and that is usually the case. However, there are
some cases when a finally block does not execute:
• Let’s take an example where we try to create a new file using FileWriter and write data to it using
PrintWriter.
An exception can occur while creating new FileWriter. It throws an IOException if the file specified
cannot be created or written to.
When an exception occurs, we will get the following output.
Value at: 0 = 0
Value at: 1 = 1
Value at: 2 = 2
Value at: 3 = 3
Value at: 4 = 4
Value at: 5 = 5
Value at: 6 = 6
Value at: 7 = 7
Value at: 8 = 8
Value at: 9 = 9
Working of try...catch...finally in Detail
Catching Multiple Exceptions
• From Java SE 7 and later, we can now catch
Its syntax is:
more than one type of exception with one
catch block. try {
// code
}
catch (ExceptionType1 | Exceptiontype2
• This reduces code duplication and increases
ex)
code simplicity and efficiency. {
// catch block
}
• Each exception type that can be handled by
the catch block is separated using a vertical
bar |.
The try-with-resources statement
The try-with-resources statement is a try statement that has one or more resource declarations.
• There might be several methods that can cause exceptions. Writing try...catch for each method
will be tedious and code becomes long and less-readable.
• throws is also useful when you have checked exception (an exception that must be handled) that
you don't want to catch in your current method.
Java throw keyword
• The throw keyword is used to explicitly throw a single exception.
• When an exception is thrown, the flow of program execution transfers from the try block to the
catch block. We use the throw keyword within a method.
• throw throwableObject;
• A throwable object is an instance of class Throwable or subclass of the Throwable class.
Example 2: Java throw keyword
class Main {
public static void divideByZero() {
throw new ArithmeticException("Trying to divide by 0");
}
Note: ArithmeticException is an unchecked exception. It's usually not necessary to handle unchecked exceptions.
Example 3: Throwing checked exception
import java.io.*;
class Main {
public static void findFile() throws IOException {
throw new IOException("File not found");
}
public static void main(String[] args) {
try {
findFile();
System.out.println("Rest of code in try block");
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
Output
File not found
The findFile() method throws an IOException with the message we passed to its constructor.
Note that since it is a checked exception, we must specify it in the throws clause.
The methods that call this findFile() method need to either handle this exception or specify it using
throws keyword themselves.
We have handled this exception in the main() method. The flow of program execution transfers from the
try block to catch block when an exception is thrown. So, the rest of the code in the try block is skipped
and statements in the catch block are executed.
USER DEFINED EXCEPTION