What this propagation means is we can nest catches...
try {
try {
// Operation
} catch (RuntimeException rte) {
// Do something with rte.
}
} catch (Exception e) {
// Do something with e if
// it's not a RuntimeException.
}
Laddered catches
try {
// Operation
} catch (OurException oe) {
// Do something with oe
} catch (Exception e) {
// Do something with e if
// it's not of type OurException.
}
Sorting out
All exceptions except RuntimeExceptions, must be caught.
The usual thing in debugging is to print the error and the stack trace.
e.printStackTrace();
Can also write its name to a standard error log...
System.err.println(e);
...but this is usually the screen anyhow.
In a real program we should do something about the error so the user doesn't get a message.
Finally
If there's something you want to happen, even if there is an error, you should put it in a 'finally' block under your 'try'.
Finally blocks are always executed, even if written after returns.
try {
// Operation.
} catch (Exception e) {
// Do something with e.
} finally {
// Do something important.
}
Making Exceptions
By saying that a method or an object must catch an exception, we can force programmers using our objects to prepare for problems.
We can use the keyword throws to do this.
If someone uses our object they must catch the thrown object or throw it again.
Eventually something must deal with it, or the program won't compile.
Creating
Subclass the class 'Exception' to make a new exception class, eg.
public class OurException extends Exception {
In our main class, declare that a method will be throwing an object if everything goes wrong...
public void name () throws OurException {
At some point in the code, throw the exception...
throw new OurException();
Summary
Exceptions and Errors give us a chance to manage problems without the user knowing.
The also allows us to force people who use our classes to deal with problems we know may arise.
Exceptions can be caught and handled, or thrown out of the method for someone else to deal with.
Exceptions propagate back through all the method calls and objects inside one another until they reach a suitable handler.