The final step in setting up an exception handler is providing a mechanism for cleaning up the state of the method before (possibly) allowing control to be passed to a different part of the program. You do this by enclosing the cleanup code within a
The
finally block.The
try block of the writeList method that you've been working with opens a PrintWriter. The program should close that stream before allowing control to pass out of the writeList method. This poses a somewhat complicated problem because writeList's try block has three different exit possibilities:- The
new FileWriterstatement failed and threw anIOException. - The
victor.elementAt(i)statement failed and threw anArrayIndexOutOfBoundsException. - Everything succeeded and the
tryblock exited normally.
finally block regardless of what happens within the try block. Regardless of whether control exits the writeList method's try block due to one of the three scenarios listed previously, the code within the finallyblock will be executed.This is the finally block for the writeList method. It cleans up and closes the PrintWriter.finally {
if (out != null) {
System.out.println("Closing PrintWriter");
out.close();
} else {
System.out.println("PrintWriter not open");
}
}
Is the finally Statement Really Necessary?
At first the need for afinallystatement may not be immediately apparent. Programmers often ask "Is thefinallystatement really necessary or is it just sugar for my Java?" In particular, C++ programmers doubt the need for afinallystatement because C++ doesn't have one.The need for afinallystatement is not apparent until you consider the following: how does thePrintWriterin thewriteListmethod get closed if you don't provide an exception handler for theArrayIndexOutOfBoundsExceptionand anArrayIndexOutOfBoundsExceptionoccurs? (It's easy and legal to omit an exception handler forArrayIndexOutOfBoundsExceptionbecause it's a runtime exception and the compiler won't alert you that thewriteListcontains a method call that might throw one.) The answer is that thePrintWriterdoes not get closed if anArrayIndexOutOfBoundsExceptionoccurs andwriteListdoes not provide a handler for it--unless thewriteListprovides afinallystatement.
There are other benefits to using thefinallystatement. In thewriteListexample it is possible to provide for cleanup without the intervention of afinallystatement. For example, you could put the code to close thePrintWriterat the end of thetryblock and again within the exception handler forArrayIndexOutOfBoundsException, as shown here:However, this duplicates code, making the code hard to read and prone to errors if you modify the code later. For example, if you add code to thetry {
. . .
out.close(); // don't do this; it duplicates code
} catch (ArrayIndexOutOfBoundsException e) {
out.close(); // don't do this; it duplicates code
System.err.println("Caught ArrayIndexOutOfBoundsException: " + e.getMessage());
} catch (IOException e) {
System.err.println("Caught IOException: " + e.getMessage());
}tryblock that may throw a new type of exception, you will have to remember to close thePrintWriterwithin the new exception handler (which if you're anything like me, you are bound to forget).
No comments:
Post a Comment