Handling Errors Using Exceptions |
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 afinally
block.The
try
block of thewriteList
method that you've been working with opens aPrintStream
. The program should close that stream before allowing control to pass out of thewriteList
method. This poses a somewhat complicated problem becausewriteList
'stry
block has three different exit possibilities:The runtime system always executes the statements within the
- The
new FileOutputStream
statement failed and threw anIOException
.- The
victor.elementAt(i)
statement failed and threw anArrayIndexOutOfBoundsException
.- Everything succeeded and the
try
block exited normally.finally
block regardless of what happens within thetry
block. Regardless of whether control exits thewriteList
method'stry
block due to one of the three scenarios listed previously, the code within thefinally
block will be executed.This is the
finally
block for thewriteList
method. It cleans up and closes the PrintStream.finally { if (pStr != null) { System.out.println("Closing PrintStream"); pStr.close(); } else { System.out.println("PrintStream not open"); } }Is the finally Statement Really Necessary?
At first the need for afinally
statement may not be immediately apparent. Programmers often ask "Is thefinally
statement really necessary or is it just sugar for my Java?" In particular, C++ programmers doubt the need for afinally
statement because C++ doesn't have one.The need for a
finally
statement is not apparent until you consider the following: how does thePrintStream
in thewriteList
method get closed if you don't provide an exception handler for theArrayIndexOutOfBoundsException
and anArrayIndexOutOfBoundsException
occurs? (It's easy and legal to omit an exception handler forArrayIndexOutOfBoundsException
because it's a runtime exception and the compiler won't alert you that thewriteList
contains a method call that might throw one.) The answer is that thePrintStream
does not get closed if anArrayIndexOutOfBoundsException
occurs andwriteList
does not provide a handler for it--unless thewriteList
provides afinally
statement.There are other benefits to using the
finally
statement. In thewriteList
example it is possible to provide for cleanup without the intervention of afinally
statement. For example, you could put the code to close thePrintStream
at the end of thetry
block 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 { . . . pStr.close(); // don't do this; it duplicates code } catch (ArrayIndexOutOfBoundsException e) { pStr.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()); }try
block that may throw a new type of exception, you will have to remember to close thePrintStream
within the new exception handler (which if you're anything like me, you are bound to forget).
Handling Errors Using Exceptions |