Search code examples
javaexceptiontry-catch-finally

What is the reason for this finally clause containing close() calls


I'm studying the online java course, Introduction to programming Using Java.

In the chapter on I/O the code below is introduced with the following statement:

By the way, at the end of this program, you'll find our first useful example of a finally clause in a try statement. When the computer executes a try statement, the commands in its finally clause are guaranteed to be executed, no matter what.

The program is at the end of section 11.2.1 and is a simple program that just reads some numbers in from a file and writes them in reverse order.

The relevant code in the main method is (data is a Reader and result is a Writer):

try {
    // Read numbers from the input file, adding them to the ArrayList.        
    while ( data.eof() == false ) {  // Read until end-of-file.
        double inputNumber = data.getlnDouble();
        numbers.add( inputNumber );
    }

    // Output the numbers in reverse order.        
    for (int i = numbers.size()-1; i >= 0; i--)
        result.println(numbers.get(i));

    System.out.println("Done!");        
} catch (IOException e) {
    // Some problem reading the data from the input file.
    System.out.println("Input Error: " + e.getMessage());
} finally {
    // Finish by closing the files, whatever else may have happened.
    data.close();
    result.close();
}

So I was wondering why the finally clause was useful in this case when there are no other exit points from the try or catch clauses. Couldn't the close methods just be in the body of main instead?

I thought maybe it was because there could theoretically be some other RuntimeException which could crash the program and then leave the Reader & Writers unclosed, but then wouldn't the fact that the program had crashed close them anyway?


Solution

  • Your idea is correct: The finally block will close the resources even if an unexpected exception ocurred.

    You are also right that this is irrelevant if such an exception crashes the complete application, but from looking at this code you can't decide if this is the case. There might be other exception handlers, catching that exception, so it is good and correct practice to put the closing logic in a finally block.

    Note that there still might be a bug hiding: if data.close() throws an exception, result.close() will never get called.

    Depending on your environment there are various flavours on how to fix the bug.

    • in java 7 ff you can use try-with-resources

    • if you are using Spring, there might be a proper template similar to the JdbcTemplate

    • if nothing of those applies, yes you'll have to do a try/finally inside the finally. Quit ugly. You absolutely should at least extract this into a method as suggested in the comments.

    • conceptually cleaner but rather wordy in java pre 8 is to implement the loan pattern. If you don't happen to work with scala/clojure/haskell developers it might be more confusing then anything else.