Chained Exception helps to identify a situation in which one exception causes another Exception in an application. Chained Exceptions allows to relate one exception with another exception, i.e one exception describes cause of another exception, providing more context about the cause of an error. This mechanism is particularly useful when an exception occurs as a result of another exception.
Chained exceptions, also known as nested exceptions, enable you to link one exception to another to provide a chain of causality. They allow you to maintain a sequence of exceptions, with each exception representing a different stage of the problem.
For example, imagine a situation in which a method throws an ArithmeticException because of an attempt to divide by zero. However, the actual cause of the problem was that an I/O error occurred, which caused the divisor to be set improperly. Although the method must certainly throw an ArithmeticException, since that is the error that occurred, you might also want to let the calling code know that the underlying cause was an I/O error. Chained exceptions let you handle this, and any other situation in which layers of exceptions exist.
Throwable class has some constructors and methods to support chained exceptions.
Constructors
- Throwable(Throwable cause) :- Where cause is the exception that causes the current exception.
- Throwable(String msg, Throwable cause) :- Where msg is the exception message and cause is the exception that causes the current exception.
Methods
- getCause() method – This method returns the actual cause associated with current Exception.
- initCause() method – It sets an underlying cause with invoking Exception.
public class ChainedExceptionExample {
public void main(String[] args) {
try {
throw new ArithmeticException("Top Level Exception.")
.initCause(new IOException("IO cause."));
} catch(ArithmeticException ae) {
System.out.println("Caught : " + ae);
System.out.println("Actual cause: "+ ae.getCause());
}
}
}
Chained exceptions can be carried on to whatever depth is necessary. Thus, the cause exception can, itself, have a cause. Be aware that overly long chains of exceptions may indicate poor design.
Examples
Without Chained Exceptions
public class WithoutChainedExceptionsExample {
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void method1() {
try {
method2();
} catch (Exception e) {
throw new RuntimeException("Exception in method1");
}
}
public static void method2() {
try {
method3();
} catch (Exception e) {
throw new RuntimeException("Exception in method2");
}
}
public static void method3() {
throw new RuntimeException("Exception in method3");
}
}
With Chained Exceptions
public class WithChainedExceptionsExample {
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void method1() {
try {
method2();
} catch (Exception e) {
throw new RuntimeException("Exception in method1", e);
}
}
public static void method2() {
try {
method3();
} catch (Exception e) {
throw new RuntimeException("Exception in method2", e);
}
}
public static void method3() {
try {
// Simulate an error
int result = 1 / 0; // ArithmeticException
} catch (ArithmeticException e) {
throw new RuntimeException("Exception in method3", e);
}
}
}
Advantages of Chained Exception
- More Context: Chained exceptions provide more context about the cause of an error by maintaining a chain of exceptions.
- Better Debugging: They facilitate easier debugging by providing a clear trace of the exception propagation path.
The printStackTrace() method of Java.lang.Throwable class used to print the Throwable along with other details like class name and line number where the exception occurred with its backtrace. This method prints a stack trace for this Throwable object on the standard error output stream.