EXCEPTION HANDLING IN JAVA

Exception Handling (JAVA) 

An exception is an abnormal condition that arises at run-time. So, we can consider it as a run-time error. Java's exception handling helps in bringing run-time error management into the real world of object oriented programming.

Basics of Exception Handling

A Java exception is an object that describes the error condition. When an exceptional condition arises, then the object representing the exception is created and thrown in the method that caused the error. That method can either choose to handle the exception by itself or pass it. In anyway, the exception is caught and processed. Exceptions are either generated by JAVA Run-time system or manually by the code. 

Five keywords in Java's Exception Handling

  • try

  • catch

  • throw

  • throws

  • finally

     


 General form of exception handling:

 try{
    //Your code goes here
}
catch(ExceptionType1){
    //exception handler for exception type 1
}
catch(ExceptionType2){
    //exception handler for exception type 2
}
//...
finally{
    //block of code to be executed after try block ends

Exception Types:

All exception types are the sub-classes of the built-in class Throwable. There are two subclasses that partition exception into two distinct branches. One branch is headed by Exception and the other is headed by Error. Exception class is used to handle exception conditions that user program should catch. In  this class, we can also create custom exceptions types. We also have subclass called RuntimeException which are defined for the programs that include things such as division by zero or invalid array indexing. In Error, exceptions which are not caught under normal circumstances are defined. Here, we have Java Run Time system to indicate errors having to do with the run-time environment. Example of such error is StackOverflow. 

Example to show if exception handling is not used:

Source Code:

class Main{
    public static void main(String args[]){
        int div = 100 / 0;
        System.out.println(div);
    }
}

Output:

Exception in thread "main" java.lang.ArithmeticException: / by zero

When the Java-run-time system detects the case to divide by zero, it constructs a new exception object and then throws this exception. This causes the execution of Main to stop because once an exception has been thrown, it must be caught by the exception handler.

try and catch

It is always a better option to handle a exception by yourself. This can help to prevent the program from terminating automatically. 

To handle a run-time error, simply enclose the  code that you want to monitor in the try block. Immediately after the try block, use the catch block to that specifies the exception type. you wish to catch. 

Example:(Source Code)

class Main{
    public static void main(String[] args){
        try{
            int i = 54 / 0;
            System.out.println("This will not be printed");
        }
        catch(ArithmeticException e){
            System.out.println("Division by zero");
        }
        System.out.println("After the catch block");
    }
}

Output:

Division by zero
After the catch block

We can notice that the println statement in the try block is not executed. Once an exception is thrown, the program control is transferred to the catch block. 

The scope of catch statement is restricted to those statement specified by immediately preceding try statement. A catch statement cannot catch an exception thrown by another try statement. The statements in try block are enclosed in curly braces. We cannot use try on a single statement.

Multiple catch clauses

When there are situations of having more than one exception, we can use multiple catch clauses. After one catch clause is executed, the others are bypassed. 

Example(Source Code):

class Main{
    public static void main(String[] args){
        try{
            int a = args.length;
            System.out.println("a="+a);
            int b = 34 / a;
            int c[] = { 2 };
            c[34] = 21;
        }
        catch(ArithmeticException e){
            System.out.println(e);
        }
        catch(ArrayIndexOutOfBoundsException e){
            System.out.println(e);
        }
        System.out.println("After try and catch blocks are executed");
    }
}

Output:

a=0
java.lang.ArithmeticException: / by zero
After try and catch blocks are executed

When you use multiple catch statements, it is important to remember that exception subclasses must come before any other superclasses. This is beacuse a catch statement that uses a superclass will catch exception of its type and other subclasses. Thus a subclass would never be reached if it came after superclass. In Java, unreachable code is an error.

Example(Source Code):

class Main{
    public static void main(String[] args){
        try{
            int a = 0;
            int b = 65 / a;
        }
        catch(Exception e){
            System.out.println("Generic exception catch");
        }
        catch(ArithmeticException e){
            System.out.println("This exception is never reached");
        }
    }
}

Output:

Main.java:10: error : exception ArithmeticException already caught

1 error

Nested Try statements 

 The try statements can be nested. Each time a try statement is entered, the context of that exception is pushed to stack. If an inner try statement does not have the catch for that particular exception, the stack is unwound and the next try statement's catch handler are inspected for a match. This continues until one of the catch statement succeeds or all the try statements are exhausted. 

Example(Source Code):

class Main{
    public static void main(String[] args){
        try{
            int a = args.length;
            int b = 123 / a;
            System.out.println("a = "+a);
            try{
                if(a == 1)
                    a = a / (a - a);
                if(a == 2){
                    int c[] = {1};
                    c[23] = 99;
                }
            }
            catch(ArithmeticException e){
                System.out.println("Divide by zero:"+e);
            }
        }
        catch(ArrayIndexOutOfBoundsException e){
            System.out.println("Array index out of bounds:"+e);
        }
    }
}

Output:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Main.main(Main.java:5)

Throw

The general form of throw is shown here:

 throw ThrowableInstance; 

Here, ThrowableInstance must be an object of type Throwable or a subclass of Throwable. Primitive types, such as int or char, as well as non-Throwable classes, such as String and Object, cannot be used as exceptions. There are two ways you can obtain a Throwable object: using a parameter in a catch clause or creating one with the new operator. 

The flow of execution stops immediately after the throw statement; any subsequent statements are not executed. The nearest enclosing try block is inspected to see if it has a catch statement that matches the type of exception. If it does find a match, control is transferred to that statement. If not, then the next enclosing try statement is inspected, and so on. If no matching catch is found, then the default exception handler halts the program and prints the stack trace.

Example(Source Code):

 class Main{
    static void demoproc(){
        try{
            throw new NullPointerException("demo");
        }
        catch(NullPointerException e){
            System.out.println("Caught inside demoproc");
            throw e;
        }
    }
    public static void main(String[] args){
        try{
            demoproc();
        }
        catch(NullPointerException e){
            System.out.println("Recaught:"+e);
        }
    }
}

Output:

Caught inside demoproc
Recaught:java.lang.NullPointerException: demo
 

throws

If a method is capable of causing an exception that it does not handle, it must specify this behavior so that callers of the method can guard themselves against that exception. You do this by including a throws clause in the method’s declaration. A throws clause lists the types of exceptions that a method might throw. This is necessary for all exceptions, except those of type Error or RuntimeException, or any of their subclasses. All other exceptions that a method can throw must be declared in the throws clause. If they are not, a compile-time error will result.

 This is the general form of a method declaration that includes a throws clause: 

 type method-name(parameter-list) throws exception-list

{

//body method

}

Here, exception-list is a comma-separated list of the exceptions that a method can throw. Following is an example of an incorrect program that tries to throw an exception that it does not catch. Because the program does not specify a throws clause to declare this fact, the program will not compile.  

Example(Source Code):

class Main{
    static void throwone() throws IllegalAccessException{
        System.out.println("Inside throwone");
        throw new IllegalAccessException("demo");
    }
    public static void main(String[] args){
        try{
            throwone();
        }
        catch(IllegalAccessException e){
            System.out.println("Caught"+e);
        }
    }
}

Output:

Inside throwone
Caughtjava.lang.IllegalAccessException: demo

finally

When exceptions are thrown, execution in a method takes a rather abrupt, nonlinear path that alters the normal flow through the method. Depending upon how the method is coded, it is even possible for an exception to cause the method to return prematurely. This could be a problem in some methods. For example, if a method opens a file upon entry and closes it upon exit, then you will not want the code that closes the file to be bypassed by the exceptionhandling mechanism. The finally keyword is designed to address this contingency.  

finally creates a block of code that will be executed after a try /catch block has completed and before the code following the try/catch block. The finally block will execute whether or not an exception is thrown. If an exception is thrown, the finally block will execute even if no catch statement matches the exception. Any time a method is about to return to the caller from inside a try/catch block, via an uncaught exception or an explicit return statement, the finally clause is also executed just before the method returns. This can be useful for closing file handles and freeing up any other resources that might have been allocated at the beginning of a method with the intent of disposing of them before returning. The finally clause is optional. However, each try statement requires at least one catch or a finally clause.

Example(Source Code):

class Main{
    static void procA(){
        try{
            System.out.println("inside procA");
            throw new RuntimeException("demo");
        }
        finally{
            System.out.println("procA's finally");
        }
    }
     static void procB(){
        try{
            System.out.println("inside procB");
            return;
        }
        finally{
            System.out.println("procB's finally");
        }
    }
     static void procC(){
        try{
            System.out.println("inside procC");
        }
        finally{
            System.out.println("procC's finally");
        }
    }
    public static void main(String[] args){
        try{
            procA();
        }
        catch(Exception e){
            System.out.println("Exception Caught");
        }
        procB();
        procC();
    }
}

Output:

inside procA
procA's finally
Exception Caught
inside procB
procB's finally
inside procC
procC's finally

Comments

Popular posts from this blog

THREE LEVELS OF DATA INDEPENDENCE

Python-HackerRank Problem List Comprehensions

Python Problem Solving - Lonely Integer