Exceptions

An exception is an abnormal condition that arises in a code sequence at run time. In other words, an exception is a run time error.

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, which is not recommended, therefore these exceptions are to be handled.

An exception can occur for many different reasons, below given are some scenarios where exception occurs.

  • A user has entered invalid data.
  • A file that needs to be opened cannot be found.
  • A network connection has been lost in the middle of communications or the JVM has run out of memory.

 

A Java exception is an object that describes an exceptional condition that has occurred in a piece of code.

Exception Handling Fundamentals

 Java exception handling is managed via five keywords: try, catch, throw, throws and finally. They form an interrelated subsystem in which use of one implies the use of another.

The program statements that we want to monitor for exceptions are contained within a try block. If an exception occurs within the try block, it is thrown. Our code can catch this exception using catch and handle it in some rational manner. System generated exceptions are automatically thrown by the Java run time system. To manually throw an exception, use the keyword throw. In some cases, an exception that is thrown out of a method must be specified as such by a throws clause. Any code that must be executed upon an exit from a try block is put in a finally block.

 In Java, all exceptions are represented by classes. All exception classes are derived from a class called Throwable Thus; Throwable is at the top of the exception class hierarchy. Immediately below Throwable are two subclasses that partition exceptions into two distinct branches. One branch is headed by Exception. This class is used for exceptional conditions that user program should catch. This is also the class that we will subclass to create our own custom exception types. There is an important subclass of an Exception, called RuntimeException. Exceptions of this type are defined for the programs that we write and include things such as division by zero and invalid array indexing.

The other branch is topped by Error, which defines exceptions that are not expected to be caught under normal circumstances by our program. Exceptions of type Error are used by the Java run time system to indicate errors having to do with the run time environment itself. Stack overflow is an example of such an error. These are typically created in response to catastrophic failures that are not handled by our program

Consequences of an Uncaught Exception

Catching one Java’s exceptions has a side benefits. It prevents abnormal program termination. When an exception is thrown, it must be caught be some piece of code, somewhere. In general, if your program does not catch an exception, then it will caught by the JVM. The trouble is that the JVM’s default exception handler terminates execution and displays an error message followed by a list of the method calls that lead to the exception.

Uncaught Exceptions: Before learning how to handle exceptions, it is useful to see what happens when we do not handle them. Let us consider the following program. This program includes an expression that intentionally causes a divide by zero error

public class Exception {

    public static void main (String[] args) {

        int d = 0;

        int a = 23/d;

        System.out.println ("a = "+a);

    }   

}

When the Java run time system detects the attempts to divide by zero, it constructs a new exception object and then throws this exception. This causes the execution of program to stop because once an exception has been thrown, it must be caught by an exception handler and dealt with immediately.  Any exception that is not caught by our program will ultimately be processed by the default handler provided by Java run time system

The default handler displays a string describing the exception, prints a stack trace from  the point at which the exception occurred, and terminates the program.

The above program generates following exception.

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

               at Exception.main(Exception.java:5)

Using try and catch

At the core of exception handling are try and catch. These keywords work together; we cannot use catch without try. The general form of try/catch exception handling blocks:

try{

               // block of code to monitor for errors

}

catch(ExceptionType1 exOb){

//Exception handler for ExceptionType1

}

catch (ExceptionType2 exOb){

//Exception handler for ExceptionType2

}

……

catch (ExceptionTypeN exOb){

//Exception handler for ExceptionTypeN

}

finally{

               //Block of code to be executed before try block ends

}




Here, ExceptionType is the type of exception that has occurred.




To guard against and handle a run time error, simply enclose the code that we want to monitor inside a try block. Immediately following the try block, inside a catch clause that specifies the exception type that we wish to catch. To illustrate this, let us consider the following program.




class Exception {

    public static void main (String[] args) {

        int d, a;

        try {

            d = 0;

            a = 23/d;        

          System.out.println (“This will not be printed”);  

        } catch (ArithmeticException e){

            System.out.println ("Division by zero");

        }

        System.out.println ("After try block");

    }   

}

This program generates the following output:

Division by zero

After try block

The println () inside is never executed. Once, an exception is thrown, program control transfers out of the try block into catch block. catch is not called, so execution never returns back to the try block from a catch. Thus, the line,” This will not be printed. “ is not displayed.

Multiple catch Clauses

In some cases, more than one execution could be raised by a single piece of code. To handle this type of situation, we can specify two or more catch clauses, each catching different types of exception. When an exception is thrown, each catch statement is inspected in order, and the first one whose type matches that of the exception is executed. After one catch statement executes, the others are bypassed,  and execution continues after the  try/catch block.

The following example traps two different exception types:

package inheritance;

public class MultiCatch {

    public static void main (String[] args) {

        try {

            int a = args. length;

            System.out.println ("a = "+a);

            int b = 42/a;

            int c[] = {1,2};

            c[10] = 101;

        }catch (ArithmeticException e){

            System.out.println ("Division by 0: "+e);

        }catch (ArrayIndexOutOfBoundsException e){

            System.out.println ("Array index oob "+e);

        }

        System.out.println ("After try /catch block ");

    }   

}

This program will causes a division by zero exception if it is started with no command line arguments, since a will equal zero. It will survive the division if we provide a command line argument, setting a to something larger than zero. But it cause an ArrayIndexOutOfBoundsException, since the int array c has a length of 2, yet the program attempts to assign a value to c[10]

Here is the output generated by running it both ways:

C:\>java MultiCatch

a = 0

Division by 0: java.lang.ArithmeticException: / by zero

After try /catch block

C:\>java MultiCatch Testing args

a = 2

Array index oob java.lang. ArrayIndexOutOfBoundsException: 10

After try /catch block

It is important to remember that exception subclasses must come before of their super classes. This is because a catch statement that uses a super class will catch exceptions of that type plus any of its subclasses. Thus, a subclass would never be reached if it came after its superclass.

Let us consider one more example:

package inheritance;

public class MultiCatch {

    public static void main(String[] args) {

        int num[] = {8,16,32,64,128,256,512,1024};

        int den[] = {1,0,4,0,8,0,16};

        int a;

        for(int i=0;i<num.length;i++)

        {

        try{

            a = num[i]/den[i];

            System.out.println(a);

           

        }catch(ArrayIndexOutOfBoundsException e){

            System.out.println("No matching element");

        }catch(ArithmeticException e){

            System.out.println("Cannot divide by zero");

        }

    }   

}

}

The output of above program is:

run:

8

Cannot divide by zero

8

Cannot divide by zero

16

Cannot divide by zero

32

No matching element

Nested try Statements

The try statement can be nested. That is, a try statement can be inside the block of another try. Each time a try statement is entered, the context of that exception is pushed on the stack. If an inner try statement does not have a catch handler for a particular exception, the stack is unwound and the next try statement’s catch handlers are inspected for a match. This continues until one of the catch statements succeeds, or until all of the nested try statements are exhausted. If no catch statement matches, then the Java run time system will handle the exception. Here is an example that uses nested try statements:

public class NestedTry {

    public static void main(String[] args) {

        try{

            int a = args.length+1;

            System.out.println("a = "+a);

            int b = 42/a;

            System.out.println("a = "+a);

            try{

                if(a==1)

                    a = a/(a-a);

                if(a==2){

                    int c[] = {1};

                    c[10] = 101;

                }                   

            }catch(ArrayIndexOutOfBoundsException e){

                System.out.println("Array index out of Bounds :"+e);

            }           

            int c[] = {1,2};

            c[10] = 101;

        }catch(ArithmeticException e){

            System.out.println("Division by 0: "+e);

    }   

}

}

The output of above program at different run will be:

C:\>java NestTry

Division by 0: java.lang.ArithmeticException: / by zero

C:\>java NestTry One

a = 1

Division by 0 : java.lang.ArithmeticException: / by zero

C:\>java NestTry One

a = 2

Array index out of Bounds: java.lang. ArrayIndexOutOfBoundsException: 10

Let us consider one more example:

package inheritance;

public class NestedTry {

    public static void main(String[] args) {

        int num[] = {8,16,32,64,128,256,512,1024};

        int den[] = {1,0,4,0,8,0,16};

        int a;

        for(int i=0;i<num.length;i++)

        {

        try{           

            try{               

                a = num[i]/den[i];

                System.out.println(a);

            }catch(ArrayIndexOutOfBoundsException e){

                System.out.println("No matching element :");

            } 

        }catch(ArithmeticException e){

            System.out.println("Division by 0: ");

    }  

  }

}

}

The output of above program is:

run:

8

Division by 0:

8

Division by 0:

16

Division by 0:

32

No matching element :

Using finally

Sometimes we want to define a block of code that will execute when a try/catch block is left. For example, an exception might cause an error that terminates the current method, causing its premature return. However, the method may need to perform some action before ends. For example, it may have allocated some resources that needs to be released. It is important that an exception not prevent the resource from being released. Circumstances of this type are common in programming, and Java provides a convenient way to handle them using finally

A finally block will be executed whenever execution leaves a try/catch bloc, no matter what condition causes it. That is, whether the try block ends normally or because of an exception, the last code executed is that defined by finally. The finally block is also executed if any code within the try block or any of its catch clauses returns from a method.

To specify a finally block, add it to the end of a try/catch sequence. The general form of a try/catch that includes finally is shown here:

try{

               // block of code to monitor for errors

}

catch(ExceptionType1 exOb){

//Exception handler for ExceptionType1

}

catch (ExceptionType2 exOb){

//Exception handler for ExceptionType2

}

……

catch (ExceptionTypeN exOb){

//Exception handler for ExceptionTypeN

}

finally {

               //Block of code to be executed before try block ends

}

Let us consider the following example:

public class FinallyDemo {

    public static void genException(int w){

        int t;

        int arr[] = {1};

        System.out.println("Receiving "+w);

        try{

            switch(w){

                case 0:

                    t = 10/w;

                    break;

                case 1:

                    arr[3] = 10;

                    break;

                case 2:

                    return;

            }

        }catch(ArithmeticException e){

            System.out.println("Can't divide by zero");

            return;

        }

        catch(ArrayIndexOutOfBoundsException e){

            System.out.println("Array boundary error");

        }

        finally{

            System.out.println("Always executing");

        }

    }

    public static void main(String[] args) {

   for(int i=0;i<=2;i++)

       genException(i);

}   

}

The output of above program is:

Receiving 0

Can’t divide by zero

Always executing

Receiving 1

Array boundary error

Always executing

Receiving 2

Always executing

The throw clause

System generated exceptions are automatically thrown by the Java run time system. To manually throw an exception, we use keyword throw. The general form of throw is shown here:

throw ThrowableInstance;

Here, ThrowableInstance must be object of the type Throwable or a subclass of Throwable.

There are two ways we can obtain a Throwable object: using a parameter in a catch clause or creating one with new operator.

The flow of execution stops immediately after the throw statement; an 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.

Let us consider the following example:

class ThrowDemo {

    static void throwOne(){

        System.out.println("Inside throw one");

        throw new ArithmeticException("Demo");

    }

    public static void main(String[] args) {

        try{

        throwOne();   

    }catch(ArithmeticException e){

            System.out.println(e);

    }

}
}

The throws clause

If a method is capable of causing an exception that it does not handle, it must specify this behavior so that the callers of the method can guard themselves against that exception. We can do this by specifying 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 the 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. Here is the general form of a method that includes a throws clause.

return type meth-name (param-list) throws except-list {

//body

}

Let us consider the following code.

import java.io.*;

public class ThrowDemo {

    public static char prompt(String s)throws IOException{

        System.out.println(s);

        char ch;

        ch = (char)System.in.read();

        return ch;

    }

    public static void main(String[] args) {

        char ch;

        try{

            ch = prompt("Enter any character");

            System.out.println("You entered "+ch);

        }catch(IOException e){

            System.out.println(e);

        }

    }

}

Java’s Built-In Exceptions

Inside the standard package java.lang, Java defines several exception classes. The most general of these exceptions are subclasses of the standard type RuntimeException. Since java.lang is implicitly imported into all Java programs, most exceptions derived from RuntimeException are automatically available. Furthermore they are not included in any method’s throws list. In the language of Java, these exceptions are called unchecked exceptions because the compiler does not check to see if a method handles or throws these exceptions. The following table shows Java’s unchecked exceptions

Unchecked Exception

Unchecked exceptions are ignored at compile time and don’t forces programmers to handle them. These exceptions are checked at runtime. They are logical programming errors and extend the java.lang.RuntimeException class. ArrayIndexOutOfBounndsException, ArithmeticException, NullPointerException etc are examples of unchecked exceptions.

Exception Meaning
ArithmeticException Caused by math error such as division by zero.
ArrayIndexOutOfBoundsException Caused by bad array indexes.
ArrayStoreException Caused when a program tries to store the wrong type of data in an array.
ClassCastException Invalid cast
EnumConstantNotPresentException An attempt is made to use an undefined enumeration value
IllegalArgumentException Illegal argument used to invoke a method
IllegalMonitorStateException Illegal monitor operation such as waiting on an unlocked thread
IllegalStateException Environment or application is in incorrect state
IllegalThreadStateException Requested operation not compatible with current thread state
NegativeArraySizeException Array created with a negative size
NullPointerException Invalid use of a null reference
NumberFormatException Invalid conversion of a string to a numeric format
SecurityException Attempt to violate security
StringIndexOutOfBounds Attempt to index outside the bounds of a string
TypeNotPresentException Type not found.
UnsupportedOperationException An unsupported operation was encountered

Table:  Java’s unchecked RuntimeException Subclasses

The java.lang package also defines exceptions that must be included in a method’s throws list if that method can generate one these exceptions that does not handle it, itself. These exceptions are called checked exceptions. The following table shows some checked exceptions

Checked Exceptions:

Checked exceptions are checked at compile time and forces programmers to deal with the exceptions otherwise program will not compile. Normally these are exceptions raised due to user error. They extend the java.lang.Exception class. IOException, SQLException etc are examples of checked exceptions

 

Exception name Meaning
ClassNotFoundException Class not found
CloneNotSupportedException Attempt to clone an object that does not implement the Cloneable interface
IllegalAccessException Access to create an object of an abstract class or interface
InstantiationException Attempt to create an object of an abstract class or interface
InterruptedException One thread has been interrupted by another thread
NoSuchMethodException A requested method does not exist.

Table: Java’s Checked Exceptions defined in java.lang

Creating Exception Sub classes

 

Although java’s built-in exceptions handle most common error, Java’s exception handling mechanism is not limited to these errors. In fact, part of the power of Java’s approach to exceptions is its ability to handle exceptions that we create which corresponds to errors in your own code. Creating such exception is an easy. Just define a subclass of Exception.

The Exception class does not define any methods of its own. It does, of course, inherit those methods provided Throwable. Thus all the exceptions, including those that you create, have the methods defined in Throwable available to them. You can override one more of these methods in Exception subclasses that you create.

Two commonly used Exception constructors are shown here:

Exception();

Exception(String msg).

The first form create an exception that has no description. The second from lets you specify a description of the exception.

Consider another example:

class NonIntResultException extends Exception{

    int n;

    int d;

    public NonIntResultException(int i,int j){

        n =i;

        d = j;

    }

    public String toString(){       

        return "Result of "+n+ "/"+d+" is not integer";       

    }

}

public class CustomExceptionDemo {

    public static void main(String[] args){

    int[] numer = {4,8,15,32,64,127,256,512};

    int[] denom = {2,0,4,4,0,8};

    for(int i=0;i<numer.length;i++){

    try{

        if(numer[i]%denom[i]!=0)

         throw new NonIntResultException(numer[i],denom[i]);

        System.out.println(numer[i]+"/"+denom[i]+"is"+numer[i]/denom[i]);

    }

    catch(ArithmeticException e){

        System.out.println("can't divide by zero");

    }

    catch(ArrayIndexOutOfBoundsException e){

        System.out.println("No matching element found");

    }

    catch(NonIntResultException exc){

        System.out.println(exc);

    }

}

}  

}

Output:

4/2 is 2

can’t divide by zero

Result of 15/4 is not integer

32/4 is 8

can’t divide by zero

Result of 127/8 is not integer

No matching element found

No matching element found


Didn't Find Any Subjects/Contents?

Click on the contribute button to contribute subjects materials on Study Notes Nepal.

Contribute

Leave a Reply

Your email address will not be published. Required fields are marked *


Join Our Facebook Community Group

Study Notes Nepal