I just had a pretty painful troubleshooting experience in troubleshooting some code that looked like this:
try {
doSomeStuff()
doMore()
} finally {
try-finally
may help you to reduce copy-paste code in case a method has multiple return
statements. Consider the following example (Android Java):
boolean doSomethingIfTableNotEmpty(SQLiteDatabase db) {
Cursor cursor = db.rawQuery("SELECT * FROM table", null);
if (cursor != null) {
try {
if (cursor.getCount() == 0) {
return false;
}
} finally {
// this will get executed even if return was executed above
cursor.close();
}
}
// database had rows, so do something...
return true;
}
If there was no finally
clause, you might have to write cursor.close()
twice: just before return false
and also after the surrounding if
clause.
In my opinion, it's more the case that finally
with a catch
indicate some kind of problem. The resource idiom is very simple:
acquire
try {
use
} finally {
release
}
In Java you can have an exception from pretty much anywhere. Often the acquire throws a checked exception, the sensible way to handle that is to put a catch around the how lot. Don't try some hideous null checking.
If you were going to be really anal you should note that there are implied priorities among exceptions. For instance ThreadDeath should clobber all, whether it comes from acquire/use/release. Handling these priorities correctly is unsightly.
Therefore, abstract your resource handling away with the Execute Around idiom.
Not at all.
What's wrong is the code inside the finally.
Remember that finally will always get executed, and is just risky ( as you have just witnessed ) to put something that may throw an exception there.
I'd say a try block without a catch block is an anti-pattern. Saying "Don't have a finally without a catch" is a subset of "Don't have a try without a catch".
I think it's far from being an anti-pattern and is something I do very frequently when it's critical do deallocate resources obtained during the method execution.
One thing I do when dealing with file handles (for writing) is flushing the stream before closing it using the IOUtils.closeQuietly method, which doesn't throw exceptions:
OutputStream os = null;
OutputStreamWriter wos = null;
try {
os = new FileOutputStream(...);
wos = new OutputStreamWriter(os);
// Lots of code
wos.flush();
os.flush();
finally {
IOUtils.closeQuietly(wos);
IOUtils.closeQuietly(os);
}
I like doing it that way for the following reasons:
I use try/finally in the following form :
try{
Connection connection = ConnectionManager.openConnection();
try{
//work with the connection;
}finally{
if(connection != null){
connection.close();
}
}
}catch(ConnectionException connectionException){
//handle connection exception;
}
I prefer this to the try/catch/finally (+ nested try/catch in the finally). I think that it is more concise and I don't duplicate the catch(Exception).