Showing posts with label finally. Show all posts
Showing posts with label finally. Show all posts

Monday, 4 July 2011

Do not return in a finally block: return will swallow your exceptions

I was recently working on a code, which was failing without giving any exception. So I had to add lots of logging to the code, to see where is the bug. I caught nothing via this method.
So I decided to check out the module source code and yeah finally I found it while debugging. The module was correctly implementing what was required and generating the required Exception as expected.

The author, unfortunately, forgot one of the rules of the Java Language and was returning from a finally block, effectively discarding the exception that was launched just a couple of lines before.

That's amazing how many times I see people returning from a finally block without understanding what the code is intended to do.

Still not convinced?

Run this:
@Test
public void hello() {
try {
throw new UnsupportedOperationException();
} finally {
return;
}
}

No exception is thrown. Surprised? You should not. There are plenty of variations of this theme out there. Nevertheless, if you're still surprised that the hello() method completes without throwing an UnsupportedOperationException, please read on.

try/catch/finally blocks

According to the Java Language Specification, this is a simplified vision of what happens during the execution of a finally block (you can read the normative documentation here):
  • If the finally block completes normally, then the try statement completes abruptly for reason R.
  • If the finally block complete abruptly for reason S, then the try statement completes abruptly for reason S.
As you may notice in the JLS, then, the "reason" a try statement completes with will always be affected by an abrupt completion of a finally block. Said in other words, the finally block will "decide" what happens later.

You probably though many times about what happens if an exception is thrown in a finally block, don't you? Perhaps you even tested that case: the exception that will be propagated up the stack will be the exception launched in the finally block. That's not surprising, after all, and that's why you should carefully check that the code in finally blocks don't fail without control.

So far, so good. But what happens, then, when a return statement is executed inside a finally block?

The return statement

What Java programmers often misunderstand is the very nature of a return statement. The Java Language Specification is clear about that:

The return statement always completes abruptly.

That's why exceptions launched in try or catch blocks (the "reason" of their abrupt completion) are simply ignored and not relaunched when a finally block completes abruptly with a return statement, being that the "resulting" reason of the abrupt completion of the try statement, as seen in the previous section.

Lesson learned

I personally don't see any good reason, unless you want any exception to be swallowed, to return in a finally block: it defies the very reason for try/catch blocks to exist.

Do think twice (or more...) before using this construct: chances are you're doing a favor to others and yourself if you avoid it.

Monday, 16 May 2011

Is the finally Statement Really Necessary in java?

At first the need for a finally statement may not be immediately apparent. Programmers often ask "Is the finally statement really necessary or is it just sugar for my Java?" In particular, C++ programmers doubt the need for a finally statement because C++ doesn't have one.The need for a finally statement is not apparent until you consider the following: how does the PrintWriter in the writeListmethod get closed if you don't provide an exception handler for the ArrayIndexOutOfBoundsException and anArrayIndexOutOfBoundsException occurs? (It's easy and legal to omit an exception handler for ArrayIndexOutOfBoundsExceptionbecause it's a runtime exception and the compiler won't alert you that the writeList contains a method call that might throw one.) The answer is that the PrintWriter does not get closed if an ArrayIndexOutOfBoundsException occurs and writeList does not provide a handler for it--unless the writeList provides a finally statement.
There are other benefits to using the finally statement. In the writeList example it is possible to provide for cleanup without the intervention of a finally statement. For example, you could put the code to close the PrintWriter at the end of the try block and again within the exception handler for ArrayIndexOutOfBoundsException, as shown here:

try {
. . .
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());
}

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 the try block that may throw a new type of exception, you will have to remember to close thePrintWriter within the new exception handler (which if you're anything like me, you are bound to forget).


Saturday, 12 March 2011

try - catch - finally : Catching the exception in java

The syntax for the usage of try, catch and finally block is given below.
try{
//some java statements which can throw exception
???
}
catch(<exceptionclass1> <obj1>){
//deal with exception
}
finally{
//close open streams etc...
} 



We have already seen the class which has to deal with the exception here.

Now that you've familiarized yourself with the ListOfNumbers class and where the exceptions can be thrown within it, you can learn how to write exception handlers to catch and handle those exceptions.
The three sections that follow cover the three components of an exception handler -- the try, catch, and finally blocks. So dealing with exceptions one by one :



The try Block


The first step in writing an exception handler is to enclose the statements that might throw an exception within a try block. The try block is said to govern the statements enclosed within it and defines the scope of any exception handlers (established by subsequent catch blocks) associated with it.

PrintWriter out = null;

try {
System.out.println("Entering try statement");
out = new PrintWriter(
new FileWriter("OutFile.txt"));

for (int i = 0; i < size; i++)
out.println("Value at: " + i + " = " + victor.elementAt(i));
}
The try statement governs the statements enclosed within it and defines the scope of any exception handlers associated with it.
Now if Exception is thrown, it should be handled by catch block or the finally block. So lets see next section.


The catch Block(s)



Next, you associate exception handlers with a try block by providing one or more catch blocks directly after the try block. You associate exception handlers with a try statement by providing one or more catch blocks directly after the try block:

try {
. . . 
} catch ( ExceptionClass1 obj1. . ) {
. . . 
} catch ( . . . ) {
. . . 
}


The finally Block


Java's finally block provides a mechanism that allows your method to clean up after itself regardless of what happens within the try block. Use the finally block to close files or release other system resources.

Putting It All Together


The previous sections describe how to construct the try, catch, and finally code blocks for the writeList example. Now, let's walk through the code and investigate what happens during three scenarios.