Sunday, August 12, 2007

Close resource inside and only inside finally block

Always close any resource (network connection, database connection, file stream) inside and only inside finally block. Don't close it inside try block. What is the problem of closing it inside try block? consider the following example:

try {
String fileName = ...;
InputStream input = new FileInputStream(fileName);
// read theContentOfTheFile
input.close();
retrun theContentOfTheFile;
} catch (IOException e) {
// log the exception
return null;
}

If an exception is thrown while reading theContentOfTheFile, the FileInputStream will never be closed.

A better solution but not totally perfect:
InputStream input = null;
try {
String fileName = ...;
input = new FileInputStream(fileName);
// read theContentOfTheFile
input.close();
retrun theContentOfTheFile;
} catch (IOException e) {
// log the exception
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
// do nothing
}
}
}

If no exception is thrown inside the try block, then before returning from the method the finally block will also be executed. That means we are trying to close the same stream twice. So, an exception will always be thrown form the input.close() inside the finally block.

The best solution:
InputStream input = null;
try {
String fileName = ...;
input = new FileInputStream(fileName);
// read theContentOfTheFile
retrun theContentOfTheFile;
} catch (IOException e) {
// log the exception
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
// do nothing
}
}
}

In this example the input.close() is granted to be executed once and only once.