[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, these are also called as compile time exceptions. For example,
IOException
,SQLException
, etc.Runtime Exceptions: An unchecked exception that occurs during the execution, these are also called as runtime exceptions. These include programming bugs, such as logic errors or improper use of an API. Note, runtime exceptions are ignored at the time of compilation. For example,
ArithmeticException
,NullPointerException
,ArrayIndexOutOfBoundsException
, etc.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.
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
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