An exception is an error condition that occurs at the run time. The reason for the runtime error/Exception could be many, like code error, system resources, invalid input etc. Some of the programming languages like C do not provide support for exception handling mechanisms, but Java has an effective way of handling exceptions. we will dig deep into the details of exception handling in the coming sections. So here is the question that may arise now, if "Exception" is an error condition then what is the difference between an exception and an error. Lets try to answer the question using the below figure.
Like shown in the above figure (With out exception handling), if there is an error at statement 4, the program execution is stopped (a good/Safe program handles the error condition with an appropriate "return code (Error code)"). A program with exception handling mechanism, will allow the program to continue execution even after the error statement-4. With exception handling, the program is not terminated abruptly and it also give a better control on the program flow. Another advantage of exception handling is that, it gives the program a chance to rectify itself. For instance, in the above example, statement 7 could rectify the "cause of the error" at statement 4 or could have an alternate solution for the error at statement. 4.Exception handling gives the program a chance to rectify itself by not terminating the program execution abruptly and doing the right thing when an error occurs.
Now that we have understood the generic concept of exception handling, let us see how it is achieved in Java. For that, Java provides the following keywords try, catch, throw, throws and finally. Try/Catch block, all the code that needs to be protected from exceptions would be in the "try block" and the exceptions in the try block are caught in the "catch block".
In the following figure, we show a simple try/catch block. After the execution is hit, the control directly jumps to the appropriate catch block. In this case, "Catch Block-1" as this is the only one available.
If needed, a single try block can have more than one catch blocks. Multiple catch blocks under one "try block" implies that, the try block is equipped to handle multiple types of exceptions. After the execution is hit, the control directly jumps to one of the appropriate catch blocks. In this case, it could be "Catch Block-1" or "Catch Block-2".
In the above figure, notice that we use two exception types (ArithmeticException and Exception) in the two catch blocks. All the arithmetic exceptions in the try block (divide by zero or never ending divisions etc are some of the examples) are handled by the ArithmeticException catch block and all the other remaining exceptions are handled by the catch block (Exception e2).
Here is the sample program that demonstrates the concept of "Exception handling".
public class exceptionHandlingExample { public static void main(String[] args) { int result = 0; int var1= 200; try { System.out.println(" This statement is executed"); result = var1/0; // Any thing below this will not be executed. result = result + 25; System.out.println(" This statement is not executed"); } catch(ArithmeticException e1) { System.out.println(" Catch Block, Arithmetic Exception "); result = 1; // Self correction, we may want to set result to 1. } catch (Exception e2) { System.out.println(" Catch Block, Generic Exception"); } // The statements after the try block are executed after the catch block. result = result + 1; System.out.println(" This is executed, Result: " + result); } }
Let us understand Java's exception handling concepts along with code flow, with the help of an example program. Notice the error in the statement "result = var1/0", this statement leads to "divide by 0 Arithmetic exception". This exception is caught by the Arithmetic Exception catch block. After the error statement, no other statements in the try block are executed as the control directly jumps to the catch block. Notice the behavior in the output below.
Compile/Run this program and here is the output:
This statement is executed Catch Block, Arithmetic Exception This is executed, Result: 2
Ty/Catch blocks can also be nested, and there is no limit in the depth of it. However, we should be careful in using nested try/catch blocks as it might cause unnecessary confusion/complexity, if there are too many nested try/catch blocks.
In the following figure, we show nested try/catch blocks. After the execution is hit, the control jumps to the catch block in the respective scope. Thus, an execution in the outer try block (let us say, statement2) would jump to the outer catch block "Catch Block-1". In this case, nothing inside the Try Block-2 would be executed. Similarly, an execution in the inner try block (let us say, statement7) would jump to the inner catch block "Catch Block-2".
Here is an example program that demonstrates the use of nested try/catch.
public class exceptionHandlingExample { public static void main(String[] args) { int result = 0; int var1= 200; int arrayVar[] = new int[5]; try { // Try Block-1 arrayVar[0] = 20; System.out.println(" Try Block-1: This statement will be printed"); arrayVar[6] = 30; System.out.println(" Try Block-1: This statement will not be printed"); try { // Try Block-2 System.out.println(" Try Block-2: This statement is executed"); result = var1/0; // Any thing below this will not be executed. System.out.println(" This statement is not executed"); } catch(ArithmeticException e1) { System.out.println(" Try Block-2:Catch Block, Arithmetic Exception "); result = 1; // Self correction, we may want to set result to 1. } catch (Exception e2) { System.out.println(" Try Block-2:Catch Block, Generic Exception"); } } catch (Exception e3) { System.out.println(" Try Block-1: Catch Block, Generic Exception"); } result = result + 1; System.out.println(" This is executed, Result: " + result); } }
Notice the below output, once the exception in the outer most try block (Try Block-1) is hit, the control directly jumps to the corresponding catch block and all the statements between them are skipped.
Compile/Run this program and here is the output:
Try Block-1: This statement will be printed Try Block-1: Catch Block, Generic Exception This is executed, Result: 1
This statement("arrayVar[6] = 30;") in the above example has been commented out and here is the output.
Try Block-1: This statement will be printed Try Block-1: This statement will not be printed Try Block-2: This statement is executed Try Block-2:Catch Block, Arithmetic Exception This is executed, Result: 2