Exception Handling


An exception is an abnormal condition that is caused by java run time error in the program. Whenever java run time system encounter some exceptional condition, an object representing that exception is created and thrown by the java run time system.
This exception need to be caught and handled properly for the correct functioning of our program, otherwise program will terminate after showing error message. The exception can be handled in the same method in which it arises or it can be passed on to handle somewhere else.
This process is known as exception handling.
Exception handling is done using five keywords:- try, catch, throw, throws and finally. It includes the following steps -
  1. The program code that you want to monitor for exception is placed within the try block.
  2. If an exception occurs in the try block, it is thrown by java run time system. It will be caught by using catch and processed accordingly.
  3. Exceptions generated by the system are thrown by the run time system automatically. If you want to throw your own exceptions manually then you can throw them using throw keyword.
  4. If you want to throw the exception out of the method in which it is generated, you can throw them using the throws keyword.
  5. If you want to be assured that some code will be definitely executes whether exception occur or not, then you can place that code in finally block.
The general form of exception handling block is as follows -
try
{
  // code that you want to monitor for exception
}
catch(ExceptionType1 ex)
{
  // code to handle the generated exception
}
catch(ExcptionType2  ex)
{
  // code to handle the generated exception
}
finally
{
// code that you defiantly wants to execute whether exceptions occur or not 
}

 

Types of Exceptions -


Throwable class -

The parent class of all types of exceptions is Throwable class. All types of exceptions are derived from Throwable class.

Error class -

The exceptions defined by Error and its subclasses are comes under the category of Error exceptions. These types of exceptions represent conditions that you are not supposed to handle i.e. you are not expected to catch and handle them.
Error has three direct subclasses - ThreadDeath, LinkageError, and VirtualMachineError.

Exception class -

It is divided into 2 categories Checked and Unchecked Exceptions.

1- Unchecked Exceptions -

All classes that extends RuntimeException class or its subclasses comes under the category of unchecked exceptions.
It is not always necessary to catch and handle unchecked exceptions, your code will compile successfully even if you include exception handling code or not. But if exception arise program will not run and terminate there.
Some common subclasses of RuntimeException are as follows -
Exception Class Cause of Exception
ArithmeticException Caused by mathematical errors such as divided by zero.
NumberFormatException Caused when a conversion between string and number fails.
ArrayIndexOutOfBoundsException Caused when trying to use array index that is outside the bounds of array.
NullPointerException Caused by referencing a null object.
StringIndexOutOfBoundsException Caused when a program attempt to access a nonexistent character position in a string.
ClassCastException Caused when tried to cast an object to an invalid type.

Example -

public class Call {

    public static void main(String[] args) {

        int a,b,c;
        try
        {
            a=10;
            b=0;
            c=a/b;
            System.out.println("This will not be printed");
        }
        catch(Exception ex)
        {
            a=b=c=-1;
            System.out.println(a+"  "+b+ "  "+c);
            System.out.println("Divide by zero Arithmetic Exception");
        }
      System.out.println("After catch block");
    }
}

 

Output -

-1  -1  -1
Divide by zero Arithmetic Exception
After catch block

 
Note that the statement System.out.println("This will not be printed"); will not be run because in the previous statement an exception has occurred, so Java run time system will create an object representing that exception and throw that to matching catch block. And catch block will gets executed. So any statements after exception has occur within try block, will not executes.

Displaying description of Exception -

There are different methods to display the description of exceptions -
1- The catch block in the above program can be rewritten as follows -
catach(Exception ex)
{
  System.out.println(ex);
}

And this block will produce the output - java.lang.ArithmeticException: / by zero
As we already know when we try to print any object in println() method it will call toString() method, So here ex.toString() will run and produce the description of exception.
This is because Throwable class has overridden toString() method of Object class to print the detail of exception.

2- The second method to display description of exception is to use getMessage() method as follows -
        catch(Exception ex)
        {
            System.out.println(ex.getMessage());
        }

    
And this block will produce the output - / by zero
It displays a short description of exception.

3- The third method to get the full detail of exception is to use printStackTrace() method as follows -
       catch(Exception ex)
        {
            ex.printStackTrace();
        }

 
And this block will produce the output - java.lang.ArithmeticException: / by zero at call.Call.main(Call.java:17)
It displays a full description of exception including line number at which exception occur, package, class and method name in which exception occur.

Multiple catch blocks -

A single piece of code within try block may throw more than one exception in that case we need more than one catch statement to handle each exception.
When exception is thrown by java run time system, each catch statement is inspected in order from top to bottom one by one, and the first one whose type is same as that of exception thrown will gets executed and remaining catch statements will be bypassed and execution continues after try/catch block.

Example -

public class Call {

    public static void main(String[] args) {

        int a=0,b=0,c=0;
        try
        {
            a= Integer.parseInt(System.console().readLine("Enter a"));
            b= Integer.parseInt(System.console().readLine("Enter b"));
            c=a/b;
        }
        catch(NumberFormatException ex)
        {
            System.out.println(ex);
            a=b=c= -1;
        }
        catch(ArithmeticException ex)
        {
            System.out.println(ex);
            a=b=c= -2;
        }
        catch(Exception ex)
        {
            System.out.println(ex);
            a=b=c= -3;
        }
        finally
        {
            System.out.println(a+"  "+b+"  "+c);
        }
        }
} 

Output -

Enter a
10
Enter b
0
java.lang.ArithmeticException: / by zero
-2  -2  -2

Here we have entered the value of b zero, so an ArithmeticException: / by zero will be thrown by java run time system.
Here we have entered the value of b zero, so an ArithmeticException: / by zero will be thrown by java run time system.
First it will inspect the first one and find no matching so forward to next one and find the matching exception class.
So second catch block gets executes that display the detail of exception and set the value of a, b and c to -2, and third catch block will be bypassed by compiler.
Note - finally block will always run even if exception occurs or not. So it gets executed and display the values of a, b and c.

Unreachable code error -

While defining multiple catch clauses, always remember that exception child class must come before its parent class.
This is because any exception parent class can catch its own type exceptions as well as all of its child class?s exceptions too.
So child class will never be reached if it comes after its parent class. And catch clause containing child class exception becomes unreachable.
And it is a compile time error in java, if any code becomes unreachable.
Consider the following example -
public class Call {

    public static void main(String[] args) {

        int a=0,b=0,c=0;
        try
        {
            a= Integer.parseInt(System.console().readLine("Enter a"));
            b= Integer.parseInt(System.console().readLine("Enter b"));
            c=a/b;
        }
          catch(Exception ex)
        {
            System.out.println(ex);
            a=b=c= -3;
        }
        catch(NumberFormatException ex)
        {
            System.out.println(ex);
            a=b=c= -1;
        }
        catch(ArithmeticException ex)
        {
            System.out.println(ex);
            a=b=c= -2;
        }
      
        finally
        {
            System.out.println(a+"  "+b+"  "+c);
        }
        }
}

     
In the above example Exception is the parent class of NumberFormatException and ArithmeticException so these both exceptions will be cached by the first catch block.
So second and third cache clocks never execute and become unreachable.
So here your program will not compile and run.

Different places to handle exceptions -

We can handle exception either in the same class where they occur or in some other class that is using methods of that class that may generate exceptions.

Example 1 - Handling exception in the same class -

class Demo
{
    int a, b, c;
    public void input()
    {
        try
        {
        a = Integer.parseInt(System.console().readLine("Enter a"));
        b = Integer.parseInt(System.console().readLine("Enter b"));
        c = a/b;
        }
        catch(ArithmeticException ex)
        {
            System.out.println(ex);
            a=b=c=-1;
        }
        catch(NumberFormatException ex)
        {
            System.out.println(ex);
            a=b=c=-2;
        }
        catch(Exception ex)
        {
            System.out.println(ex);
            a=b=c=-3;
        }
    }
    
    public void disp()
    {
        System.out.println(a+"  "+b+"  "+c);
    }
}

public class Call {

    public static void main(String[] args) {
        
        Demo d1 = new Demo();
        d1.input();
        d1.disp();

    }
}
         

Output -

Enter a
10
Enter b
hello
java.lang.NumberFormatException: For input string: "hello"
-2  -2  -2

     

Example 2 - Handling exception in other class -

class Demo
{
    int a, b, c;
    public void input()
    {
       
      a= Integer.parseInt(System.console().readLine("Enter a"));
      b= Integer.parseInt(System.console().readLine("Enter b"));
      c= a/b;
    }
    
    public void disp()
    {
        System.out.println(a+"  "+b+"  "+c);
    }
    
    public void setVal(int x, int y, int z)
    {
        a = x;
        b = y;
        c = z;
    }
}

public class Call {

    public static void main(String[] args) {
        
        Demo d1 = new Demo();
        try
        {
        d1.input();
        }
        catch(ArithmeticException ex)
        {
            System.out.println(ex);
            d1.setVal(-1, -1, -1);
        }
        catch(NumberFormatException ex)
        {
            System.out.println(ex);
            d1.setVal(-2, -2, -2);
        }
        catch(Exception ex)
        {
            System.out.println(ex);
            d1.setVal(-3, -3, -3);
        }
        
        d1.disp();
    }
}
 

Output -

Enter a
10
Enter b
hello
java.lang.NumberFormatException: For input string: "hello"
-2  -2  -2

     

Throwing our own Exceptions -

You can throw exceptions explicitly by using the throw keyword. It has the following syntax -
Throw ThrowableObject;
Where ThrowableObject is an object of class Throwable or any of its subclass.

Example -

class Demo
{
    int a, b, c;
    public void input()
    {
       
      a= Integer.parseInt(System.console().readLine("Enter a"));
      if(a < 0)
      {
          throw new RuntimeException("a is wrong");
      }
      b= Integer.parseInt(System.console().readLine("Enter b"));
      if(b < 0)
      {
          throw new RuntimeException("b is wrong");
      }
    
      c= a/b;
    }
        
    public void disp()
    {
        System.out.println(a+"  "+b+"  "+c);
    }
    
    public void setVal(int x, int y, int z)
    {
        a = x;
        b = y;
        c = z;
    }
}

public class Call {

    public static void main(String[] args) {
        
        Demo d1 = new Demo();
        try
        {
        d1.input();
        }
        catch(ArithmeticException ex)
        {
            System.out.println(ex);
            d1.setVal(-1, -1, -1);
        }
        catch(NumberFormatException ex)
        {
            System.out.println(ex);
            d1.setVal(-2, -2, -2);
        }
        catch(RuntimeException ex)
        {
            System.out.println(ex);
            d1.setVal(-3, -3, -3);
        }
        catch(Exception ex)
        {
            System.out.println(ex);
            d1.setVal(-4, -4, -4);
        }
        
        d1.disp();
    }
} 

     

Output -

Enter a
10
Enter b
-1
java.lang.RuntimeException: b is wrong
-3  -3  -3
     

2- Checked Exceptions -

All the classes that extends the Exception or its subclasses except the RuntimeException comes under the category of Checked Exception.
In case of checked exceptions, the compiler will check whether you've handled the exception in a method where the exception may be thrown or you?ve indicated that the method can throw such an exception.
If you do neither, your code won't even compile.
Some common Checked Exceptions are as follows -
Exception Class Cause of Exception
IOException Caused by Input Output stream related exception
SQLException Caused while executing queries on database related to SQL syntax
ClassNotFoundException Caused when required class is not found

Example -

import java.io.IOException;   
class Demo
{
    private int roll;
    private int marks;
    
     public void setRoll(int r) throws IOException
     {
        if(r < 0)
        {
            throw new IOException("Roll is wrong");  // checked exception
        }
        else
        {
            roll = r;
        }
    }

    public int getRoll() 
    {
        return roll;
    }
    
    public void setMarks(int m) 
    {
        if(marks <0 && marks >100)
        {
            throw new RuntimeException("marks is wrong");
        }
    }
   
    public int getMarks() 
    {
        return marks;
    } 
    
}

public class Call {

    public static void main(String[] args) {
        
        Demo d1 = new Demo();
        try
        {
            d1.setRoll(-2);
            d1.setMarks(80);
            System.out.println(d1.getRoll());
            System.out.println(d1.getMarks());
        }
        catch(IOException ex)
        {
            System.err.println(ex);
        }
        catch(RuntimeException ex)
        {
            System.out.println(ex);
        }
        catch(Exception ex)
        {
            System.out.println(ex);
        }
      
    }
}

     

Output -

         java.io.IOException: Roll is wrong
     
If checked exceptions are not handle then the code will not even compile.
In the above example setRoll() may throw a checked exception (IOException) , so we have to handle this exception in the method where it occur using either throws clauses or using try catch block as well as in the method where we are using this class.

Throws keyword -

Throws clause is used with method declaration. It is used to throw an object of exception that a method can generate.
We generally use it when a method can generate exception but does not handle that exception, in that case we can inform the caller of method using throws keyword that this method can generate some type of exception and caller can handled the exception.
Note -
If your method can generate some checked exception, and you do not handle that exception using try/catch block, then it is compulsory to throw that exception using throws clause otherwise your code will not even compile.
However for unchecked exception it's optional.

Throws has the following syntax -
return_type   method_Name(parameter list) throws exception1, exception2,... exception n
{
 // body of method;
}

        
Note that if a method may generate more than one exception then we can throws them all by comma separated list of exceptions in method declaration.