[16]
Introduction
An exception or exceptional event is a problem that arises during the execution of a program. When an exception occurs the normal flow of the program is disrupted and the program/application terminates abnormally, therefore these exceptions need to be handled.
A Java Exception is an object that describes the exception that occurred in a program. When an exceptional event occurs in Java, an exception is said to be thrown. An exception can occur for many different reasons like when a user enters invalid data or when a file that needs to opened cannot be found or when a network connection gets lost abruptly or when the JVM runs out of memory. Mainly, exceptions are caused by users, programmers or when physical resources fail. The Exception Handling in Java is one of the robust mechanisms to handle the exceptions or runtime errors so that the normal flow of the application can be maintained.
In Java there are three categories of Exceptions:
Checked Exceptions: A checked exception is an exception that occurs at the compile time, they are also called as compile time exceptions. Checked exceptions are derived from
Exception
class. External factors like I/O and database connection cause the checked exceptions. They must be handled usingtry-catch
blocks or must be declared usingthrows
keyword. For example,IOException
&SQLException
. There are two types of checked exceptions:Fully Checked Exception: A type of checked exception where all of its child classes are also checked.
Partially Checked Exception: A type of checked exception where some of its child classes are unchecked.
Any checked exception is a subclass of Exception
. Unlike the unchecked exception, checked exception must be caught either by the caller or listed as a part of the method signature using the throws
keyword.
Runtime Exceptions: An unchecked exception that occurs during the execution, they are also called as runtime exceptions. These exceptions are derived from
RuntimeException
class. They include programming bugs, such as logical errors or improper use of an API. Note, runtime exceptions are ignored at the time of compilation. For example,ArithmeticException
,NullPointerException
&ArrayIndexOutOfBoundsException
Errors: These are not exceptions at all, but problems that arise beyond the control of the user or the programmer. For example,
OutOfMemoryError
,VirtualMachineErrorException
.
All exception classes are subtypes of the java.lang.Exception
class. The Exception
class is a subclass of the Throwable
class. Other than the Exception
class there is another subclass called Error
class which is derived from the Throwable
class.
Error vs/ Exception
In Java, errors and exceptions are both throwable objects, but they represent different types of problems that can occur during program execution. Errors are usually caused by serious problems outside the control of the program, such as running out of memory or a system crash. Errors are represented by the Error
class and its subclasses. Common examples of errors in Java include:
OutOfMemoryError
: Thrown when the Java Virtual Machine (JVM) runs out of memory.StackOverflowError
: Thrown when the call stack overflows due to too many method invocations.NoClassDefFoundError
: Thrown when a required class cannot be found.
Exception Handling Mechanism
Exception Handling is done using five keywords —
try
catch
finally
throw
throws
Using Try-catch
try
: The Javatry
block is used to enclose code that might throw an exception. It must be within the method. Thetry
block must be followed by eithercatch
orfinally
block.catch
: Thecatch
block in Java is used to handle the exception. It must be used after thetry
block only. Thecatch
block that follows thetry
block is checked, if the type of exception that has occurred is listed in thatcatch
block then the exception is handed over to thecatch
block that handles it.
Syntax —
try {
// Risky code
} catch(ExceptionName1 e) {
// Catch Block 1
} catch(ExceptionName2 e) {
// Catch Block 2
}
In the above syntax, there are two catch
blocks. In try
block, we write the code that might generate exception. If the exception is generated by the protected code then the exception is thrown to the first catch
block. If the type of the exception thrown matches ExceptionName1
, it is caught there and executed in the catch
block. Else, the exception gets passed down to the second catch
block. This continues until the exception is either caught or falls through all catches, in that case the current method stops execution.
Example —
public class JavaDemo {
public static void main(String[] args) {
try {
int arr[] = {1, 2, 3};
arr[3] = 3 / 0;
} catch(ArithmeticException e) {
System.out.println("You are trying to divide a number by 0 " + e);
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("You are trying to access an array element which does not exist " + e);
}
}
}
Output —
You are trying to divide a number by 0 java.lang.ArithmeticException: / by zero
There's a chance you might be wondering why only one of the exceptions was caught when both the exceptions are valid and should have been caught. In Java, when an exception is thrown, the program control jumps to the corresponding catch
block, and then it exits the try-catch
block entirely. It does not continue to the next catch
block or resume the try
block to potentially throw another exception. This means only the first exception encountered will be caught and handled.
In the code, the exception for dividing by zero was encountered first, so it was caught by the ArithmeticException
catch block. Since the exception was caught and handled, the program did not proceed to the next line arr[3] = ...
where the ArrayIndexOutOfBoundsException
would occur.
Another example Java program to illustrate checked exceptions where FileNotFoundException
occurred —
import java.io.*;
public class CheckedExceptionExample {
public static void main(String[] args) {
try {
// Attempt to read from a non-existent file
FileReader fr = new FileReader("nonexistent.txt");
int i;
while ((i = fr.read()) != -1) {
System.out.print((char) i);
}
}
catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
}
catch (IOException e) {
System.out.println("An I/O error occurred: " + e.getMessage());
}
}
}
Output —
File not found: nonexistent.txt (No such file or directory)
FileNotFoundException
is a checked exception in Java. It occurs when the program tries to read from a file that does not exist. If the FileReader
object is created successfully, the code attempts to read data from the file. If the file doesn't exist, a FileNotFoundException
is thrown. The catch
block specifically handles this exception by printing an informative message. General IOException
handles any other I/O exceptions that might occur during file reading (e.g., problems with file access permissions).
Nested Try-catch Blocks
In Java, a try
block within a try
block is known as Nested try
block. Nested try
blocks are used when a part of a block may cause one error while entire block may cause another error. In that case, if the inner try
block does not have a catch
handler for a particular exception then the outer try
is checked for match. This continues until one of the catch succeeds or until the entire nested try statements are done. If no catch
statements match, then the Java run-time system will handle the exception.
Syntax —
try {
try {
// Risky code
} catch(ExceptionName1 e) {
// Catch Block 1
}
} catch(ExceptionName2 e) {
// Catch Block 2
}
Example —
public class JavaDemo {
public static void main(String[] args) {
try {
int arr[] = {5, 0, 1, 2};
try {
arr[4] = arr[3] / arr[1];
} catch(ArithmeticException e) {
System.out.println("You are trying to divide a number by 0 " + e);
}
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("You are trying to access an array element which does not exist " + e);
} catch(Exception e) {
System.out.println("Generic Exception " + e);
}
System.out.println("We're out of 'try-catch' block now");
}
}
Output —
You are trying to divide a number by 0 java.lang.ArithmeticException: / by zero
We're out of 'try-catch' block now
Another example Java program to illustrate unchecked exception —
class JavaDemo {
public static void main(String args[]) {
// Here we are dividing by 0, which will not be caught at compile time
// as there is no mistake but caught at runtime because it is mathematically incorrect
int x = 0;
int y = 10;
int z = y / x;
}
}
Output —
Exception in thread "main" java.lang.ArithmeticException: / by zero
at JavaDemo.main(JavaDemo.java:11)
Finally
A finally
keyword is used to create a block of code that follows a try-catch block. A finally
block always executes regardless of whether the exception has occurred or not and is usually placed at the end of the catch
block.
Syntax —
try {
// Risky code
} catch(ExceptionName1 e) {
// Catch Block 1
} catch(ExceptionName2 e) {
// Catch Block 2
} finally {
// This block will always execute
}
Example —
public class JavaDemo {
public static void main(String[] args) {
int a[] = new int[2];
try {
System.out.println("Accessing element three " + a[3]);
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Exception thrown " + e);
} finally {
a[0] = 10;
System.out.println("The first element's value is " + a[0]);
System.out.println("This block is always executed.");
}
System.out.println("Out of the loop... try-catch-finally!");
}
}
Output —
Exception thrown java.lang.ArrayIndexOutOfBoundsException: 3
The first element's value is 10
This block is always executed.
Out of the loop... try-catch-finally!
Some pointers to keep in mind.
A
catch
clause cannot exist without atry
statement.Adding a
finally
clause for every try-catch block is not mandatory.The
try
block cannot be present without eithercatch
orfinally
clause.
Throw
When we explicitly want to throw an exception we make use of the throw
keyword. We can throw either checked or unchecked exceptions using this keyword. But, only objects of the Throwable
class or it's subclasses can be thrown. On encountering a throw
statement, the program execution ceases and the closest catch
statement is checked for matching type of the exception.
Syntax —
throw new ThrowableInstance("Demo");
Example —
public class JavaDemo {
public static void main(String[] args) {
demo();
}
public static void demo() {
try {
throw new ArithmeticException("Demo");
} catch(ArithmeticException e) {
System.out.println("Exception Caught");
}
}
}
Output —
Exception Caught
Throws
The throws
keyword is used to declare an exception. If a method does not handle a checked exception, the method must declare it using the throws
keyword. This keyword appears at the end of the method's signature. You are allowed declare multiple exceptions.
Syntax —
return_type methodName() throws exceptionClassName {
// Method Code
}
Example —
public class JavaDemo {
public static void main(String[] args) {
try {
demo();
} catch(ArithmeticException e) {
System.out.println("Exception Caught");
}
}
public static void demo() throws ArithmeticException {
System.out.println("We're inside the demo method.");
throw new ArithmeticException("Demo");
}
}
Output —
We're inside the demo method.
Exception Caught