Java Exception Handling Tutorial-2

Advanced Exception Handling in Java Tutorial with Example Programs

This post is in continuation of the previous Java Exception Handling Tutorial. After reading the previous post, the basic concept of using try and catch block should be clear. The other thing that is to be noted in context of using try and catch block is that try block can not exist alone, it must be followed by at least one catch block or finally block. The next step that you should learn about is the nesting of try blocks.

Nesting Try Blocks

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.
Below example program demonstates how the nesting of try blocks work in Java exception handling.

Program to demonstate nesting of try blocks in Java Exception Handling

import java.util.*;
class DemoExceptionHandling2{
	public static void main(String [] args){
		Scanner s = new Scanner(System.in);
		int a = 1;
		int b = 1;
		int n = 0;
		int c[] = {1};
		//enter value of B as zero to cause a divide by zero exception in Outer try block
		System.out.println("Enter value of B:");
		b=s.nextInt();
		//Outer Try Block
		try{
			System.out.println("Outer Try Block Entered!");
			System.out.println("A/B="+a/b);		//divide by zero exception occurs here if b=0
			System.out.println("No Exception has occured in Outer try block!!");
			//Inner Try Block
			try{
				System.out.println("Nested Try Block Entered!");
				System.out.println("Enter 0 to run normal, 1 or greater to cause ArrayIndexOutOfBoundsException:");
				n = s.nextInt();
				System.out.println("C= "+c[n]);
				System.out.println("Enter value of B again:");	//enter zero to cause divide by zero Arithmetic Exception
				b = s.nextInt();
				System.out.println("a/b ="+a/b);
				System.out.println("No exception in inner try block has occured!!");
			}
			//inner catch block will only catch Array Index Out of Bounds Exceptions
			catch(ArrayIndexOutOfBoundsException e){
				System.out.println("Exception caught in Inner catch block : "+e);
			}

		}
		//This outer catch block will catch Arithmetic Exceptions
		catch(ArithmeticException ae){
			System.out.println("Exception Caught in Outer Catch Block 1: "+ae);
		}
		//This outer catch block will catch all the uncaught Exceptions
		catch(Exception eo){
			System.out.println("Exception Caught in Outer Block 2: "+eo);
		}
		//finally block will execute every time
		finally{
			System.out.println("The code inside the finally block is executing...");
		}
		System.out.println("Line after try-catch-finally Block!");
	}
}
The above program simply demonstates the concept of nesting try blocks in Java. I encourage you to try it yourself by adjusting the different values and notice how and which exception is being caught where. But anyway, I would like to brief the results of the above program. When you make b=0, the exception in outer try block occurs and then the whole try block including the nested inner block is skipped and the exception is caught by first catch block (which is coded to catch ArithmeticException such as divide by zero) and then the finally block is executed followed by any code afterwards. But when you make b=1, outer try block works fine and inner try block is reached. If you make n>1, then it causes ArrayIndexOutOfBoundsException to occur, which is caught by the inner catch block. But if ArrayIndexOutOfBoundsException is not caused but a Divide by Zero exception in inner try block, then there is no corresponding catch block to catch that ArithmeticException and in that case that exception is caught in the outer catch block.

Difference between throw and throws

throw: throw keyword is used to explicitly throw any exception in your java program, till now all the exceptions that were caught by the catch block, were thrown by the Java run-time system. The general form of using throw keyword is:
throw ThrowableInstance;
Here the ThrowableInstance is an object of Throwable class or any of its subclasses. Let me remind you that Throwable is the base class of Exception class, which in turn is the base class of all the exceptions. One can use the new keyword to create the object of Throwable class.

throw new IllegalAccessException;
or
throw new IllegalAccessException("demo exception");

The above two options of throwing occurs due to the presence of at least two constructors of Throwable and all of its sub-classes. One without the parameter and one with string parameter describing that exception.
throws: throws is used with methods to signal that the method might cause some exception (s) that it is not equipped to handle, so that the calling method can do the exception handling arrangements while calling that function. If a method is capable of causing an exception that it does not handle, then it must specify the type of exceptions it can cause using throws keyword followed by the comma separated list of all the exception classes that it is suspected to cause. Any method that calls such method with throws declaration must provide means of handling all those exceptions by either enclosing the function call in try-catch-finally block or rethrowing those exceptions to its calling methods, if any.
The general form of using throws is like:
type method-name(parameter-list) throws exception-list
for example:
double anyMethod(double x, double y) throws IOException, FileNotFoundException, IllegalAccessException{//method-body}

Defining and Using your own Exceptions

Java also enables you to create your own exceptions to handle situations specific to your applications. Although most of the errors are handled by Java's built-in exceptions, but being able to create your own exceptions might come handly in some particular situations depending on your application. Creating your own Exceptions is very easy, you just need to define a subclass of Exception class and specify the constructors and the other methods you want to add to specify your particular exception scenario. This new built class does not inherit any functions from Exception class as Exception class does not even define any methods of its own; it inherits from Throwable class.
Below is the simple example to demonstate how to define your own exceptions in java.
class MyException extends Exception{
	private int i;
	MyException(int x){
		i=x;
	}
}
public class MyCustomException{
	static void displayNumber(int x) throws MyException{
		System.out.println("called displayNumber("+x+")");
		if(x>15)
		{
			throw new MyException(x);
		}
		System.out.println("MyException did not occur!");
	}
		public static void main(String args[]){
			try{
				displayNumber(5);
				displayNumber(25);
			}catch(MyException me){
				System.out.println("MyException Caught: "+me);
			}
		}
	}
Exceptions handling in java is a great tool which you can handle to ensure the smooth and uninterrupted execution of your program. The above tutorials are still the basic level tutorials meant for beginners in Java only. Once you get over with these, you can try more advanced use of the Exceptions Handling in java.
If you have any questions regarding this and the previous tutorials, you can write in the comments below.

4 comments:

  1. thanks for the tutorial, very well explained.

    ReplyDelete
  2. Great work you have done here. Thanks for posting this valuable information about Java. Webvirtue is the best Java development company in India.

    ReplyDelete

Please leave your valuable comments here...