|Navigate Exceptions topic: )|
When an exception is caught, the exception contains the stack-trace, which describes the error and shows where the exception happened, where the problem is, where the application programmer should look to fix the problem. Sometime it is desirable to catch an exception and throw another new exception. If the new exception keep a reference to the first exception, the first exception is called a nesting exception.
The above code is an example of a nesting exception. When the
Exception is thrown, by passing in the
ClassCastException object reference as a parameter, the
ClassCastException is nested in the newly created
Exception, its stack-trace is appended together. When the
Exception is caught, its stack-trace contains the original
This is a kind of exception conversion, from one exception to another. For example, calling a remote object using RMI, the calling method has to deal with
RemoteException which is thrown if something is wrong during the communication. For the application point of view,
RemoteException has no meaning, it should be transparent to the application that a remote object was used or not. So the
RemoteException should be converted to an application exception.
This conversion can also hide where the error is originated. The stack-trace starts when the exception is thrown. So when we catch and throw a new exception, the stack-trace starts at when the new exception was thrown, losing the original stack-trace. This was true with the earlier version of Java (before 1.4). Since then, a so called cause facility capabilities were built in the
A throwable contains a snapshot of the execution stack of its thread at the time it was created. It can also contain a message string that gives more information about the error. Finally, it can contain a cause: another throwable that caused this throwable to get thrown. The cause facility is also known as the chained exception facility, as the cause can, itself, have a cause, and so on, leading to a "chain" of exceptions, each caused by another.
A cause can be associated with a throwable in two ways: via a constructor that takes the cause as an argument, or via the
initCause(Throwable) method. New throwable classes that wish to allow causes to be associated with them should provide constructors that take a cause and delegate (perhaps indirectly) to one of the
Throwable constructors that takes a cause. For example:
|Code section 6.26: Chaining-aware constructor.
Because the initCause method is public, it allows a cause to be associated with any throwable, even a "legacy throwable" whose implementation predates the addition of the exception chaining mechanism to Throwable. For example:
|Code section 6.27: Legacy constructor.
Further, as of release 1.4, many general purpose Throwable classes (for example
Error) have been retrofitted with constructors that take a cause. This was not strictly necessary, due to the existence of the
initCause method, but it is more convenient and expressive to delegate to a constructor that takes a cause.
By convention, class
Throwable and its subclasses have two constructors, one that takes no arguments and one that takes a String argument that can be used to produce a detail message. Further, those subclasses that might likely have a cause associated with them should have two more constructors, one that takes a
Throwable (the cause), and one that takes a String (the detail message) and a
Throwable (the cause).