Saturday, December 20, 2014

Points to keep in mind while Handling Exceptions in Java

Exceptions are pretty easy to implement in Java, but you should be careful while applying this functionality as there can be times where Exceptions can produce unexpected results.


1. Using throws

 throws keyword is used to ignore the exception that might occur in a method and let the caller of the method care about the Exception. Although there is nothing much else that throws will do but in a some cases you might not want to use throws as it can cause the statements below the exception causing statement to not being executed. So if you want that whether or not the Exception occurs the statements below the exception causing statement should be executed as such then you cannot use throws.
     
   When an Exception occurs in the method the control is passed to the caller of the method(another method), if we use throws. But if we want the statements after the exception causing statement to execute you should add a try/catch block instead of using throws. 
Here is an example illustrating the problem with using throws :



public class ThrowsNotGoodEnough{

    public static void levelOne() throws ArithmeticException{

        System.out.println("Executing the statement that will 

                                  generate Exception");

        int a = 5/0;  //Exception causing Statement

     System.out.println("I m left alone!"); /**this statement    

                                               will not execute 
                                     if the exception occurs **/

    }
    public static void main(String args[]){

      
        try{

            levelOne();
        }catch(ArithmeticException ar){
            ar.printStackTrace();
        }
      

        System.out.println("Exiting...");

    }


}



In this Example <System.out.println("I m left alone!");> will not execute if Exception occurs as throws will throw the control to main when Exception occurs.
To avoid this circumstance you should use try/catch block instead of throws.
Here's how :


public class ThrowsNotGoodEnough{

    public static void levelOne(){

        System.out.println("Executing the statement that will generate Exception");


        try {
            int a = 5/0;    //Exception causing Statement
        }catch(ArithmeticException ae){
            ae.printStackTrace();
        }

        System.out.println("I m left alone!"); /** this statement will now execute 

                                                                      even if the exception occurs **/

    }


    public static void main(String args[]){


            levelOne();      

        System.out.println("Exiting...");

    }


}



2. Nested Exceptions(using finally)


   The term Nested Exception is used in the similar context as it is used for if-else blocks. A Nested Exception is the one which occurs inside the catch block of another Exception. Nesting of Exceptions is possible till any depth that you want but. But while implementing Nested Exception you should take of one thing which usually skips our eye and remains unnoticed.


While we handle Nested Exceptions the program may skip the code after the catch block of the Outer Exception. For instance take the following case :
  
  public class NestedException{

    public static void levelOne() throws NullPointerException{

        System.out.println("Executing Level One Method");

        try{
            int a = 5/0; //divide by zero arithmetic Exception
        }catch(ArithmeticException ae){

            System.out.println("\n\t ArithmeticException Occured \n");

            String s=null; // making sure that Exception occurs.
            System.out.println(s.toString()); // null Pointer Exception.
                                              // String object `s` intialized to null
        }finally{
            System.out.println("I am in Finally , i will be Executed!"); 

            // statement WILl BE executed , not matter what!
        }

        System.out.println("I am Left Alone. I am not in Finally"); 

                              // statement WILL NOT BE executed                                   // due to NullPointerException

    }


    public static void main(String args[]){

        try{
            levelOne();  

              // handling the Nested NullPointerException thrown by levelOne()
        }catch(NullPointerException e){
            System.out.println("\n \t Nested NullPointerException Occured \n");
        }


        System.out.println("Main Exiting...");

    }



This Example has a method names levelOne(), which contains a statement responsible for producing ArithmeticException. This ArithmeticExeption is handled in the same method levelOne() using a try/catch block.

Nothing new till now! 

In the catch block of ArithmeticException we have a statement which is responsible for the NullPointerException. This NullPointerException is the NestedException in this case. The NullPointerException is thrown by the levelOne() function , which means the caller of this function(in our case main) will handle the exception. We are handling the Exception in main using a try/catch block which will catch the NullPointerExeption in levelOne().

Now When the NullPointerException occurs the control is given back to main function to execute the try/catch block for that Exception. Now here's is the point behind all this :

   " The statement after catch block of ArithmeticException in levelOne() will only be executed if they are in finally block , otherwise they will not be executed."  

So this statement in the finally block : 

    System.out.println("I am in Finally , i will be Executed!");  

will be executed and the statement outside the finally :

    System.out.println("I am Left Alone. I am not in Finally"); 

will be skipped.

This is why we use finally block with a try/catch block , to be able to execute required statements even if an Exception occurs.