Thursday 27 February 2014

Chained Exceptions: getCause, initCause

One exception causes to throw other Exception is called chained Exception. Exception chaining is also called nesting exceptions. Some times it is good to know, what is the cause for this exception.

Throwable class support two methods to support chained exceptions.

Initialize the cause for an Exception
public Throwable initCause(Throwable cause)
Initializes the cause of this throwable to the specified value.
   Ex:
   exce1.initCause(exce2)'

Here the exception exce2 is the cause for the exception exce1.

Get the cause for an Exception
public Throwable getCause()
Returns the cause of this throwable or null if the cause is nonexistent or unknown.

Example
class CauseEx{
 static void divide(){
  try{
   int a = 10/0;
  }
  catch(ArithmeticException e){
   try{
    int a[] = new int[10];
    a[11] = 100;
   }
   catch(Exception e1){
    e1.initCause(e);
    throw e1;
   }
  }
 }

 public static void main(String args[]){
  try{
   divide();
  }
  catch(Exception e){
   System.out.println(e);
   System.out.println("Cause for this exception is " + e.getCause());
  }
 }
}
   
Output
java.lang.ArrayIndexOutOfBoundsException: 11
Cause for this exception is java.lang.ArithmeticException: / by zero
  

Throwable class supports two constructors for chained exceptions handling.

1. Throwable(Throwable cause)
Constructs a new throwable with the specified cause and a detail message.

2. Throwable(String message, Throwable cause)
Constructs a new throwable with the specified detail message and cause.

Some Points to remember

1. InitCause() called at most once. Calling this more than once cause "IllegalStateException".

Example
class CauseEx{
 static void divide(){
  try{
   int a = 10/0;
  }
  catch(ArithmeticException e){
   try{
    int a[] = new int[10];
    a[11] = 100;
   }
   catch(Exception e1){
    e1.initCause(e);
    e1.initCause(e);
    throw e1;
   }
  }
 }

 public static void main(String args[]){
  try{
   divide();
  }
  catch(Exception e){
   System.out.println(e);
   System.out.println("Cause for this exception is " + e.getCause());
  }
 }
}

Program compiles fine, But at run time below error is thrown, since initCause called twice on the same Throwable object.
      
java.lang.IllegalStateException: Can't overwrite cause
Cause for this exception is null

2. A throwable can't be cause for itself.
Example
class CauseEx{
 static void divide(){
  try{
   int a = 10/0;
  }
  catch(ArithmeticException e){
   try{
    int a[] = new int[10];
    a[11] = 100;
   }
   catch(Exception e1){
    e1.initCause(e1);
    throw e1;
   }
  }
 }

 public static void main(String args[]){
  try{
   divide();
  }
  catch(Exception e){
   System.out.println(e);
   System.out.println("Cause for this exception is " + e.getCause());
  }
 }
}

Program compiles fine, But at run time "IllegalArgumentException" thrown, Since "e1.initCause(e1)" e1 is the cause for e1, which is wrong, Throwable can't be the cause for same Throwable.

java.lang.IllegalArgumentException: Self-causation not permitted
Cause for this exception is null


3. Constructors like “Throwable(Throwable cause)”, “Throwable(String message, Throwable cause)” are initializing the cause for an exception at the time of creation of Throwable object. So Don't call the initCause() again, since it is already called.



Fill stack trace                                                 Custom Exceptions                                                 Home

No comments:

Post a Comment