Search code examples
javatry-catchtry-catch-finallyfinallytry-finally

In try/finally, does it matter what's inside the try?


Is there any functional difference?

Connection c = null;
try {
  c = getConnection();
  c.doStuff();
} finally {
  if (c!=null) c.close();
}

vs

Connection c = null;
c = getConnection();
c.doStuff();
try {
} finally {
  if (c!=null) c.close();
}

vs

Connection c = null;
try {
  c = getConnection();
} finally {
  if (c!=null) c.close();
}
c.doStuff();

I feel that all of them will do the same thing in all cases


Solution

  • An exception that occurs outside of a try-finally block is by definition an unhandled exception. That being the case, you don't have any guarantees about how the operating system or runtime will deal with it. Chances are good that an exception unwind won't be triggered, your code will simply abort (maybe abend describes it better in this discussion--"abnormal end"), and your finally block will never execute.

    The point of try-finally is to guarantee that code cleanup occurs, and occurs in the correct context.

    You must be thinking that the code in the finally block is always going to execute no matter what, and that it is going to execute after the entire method finishes, therefore it doesn't matter whether the other code is located inside or outside the try-finally construct, but that is not correct.

    So if you want any run-time guarantees of correct behavior your first example is the only correct one.

    • In your first example, you acquire and more importantly use a connection (to a database, one would presume) inside the try block. If an exception occurs within the try block, then the finally block will execute and close your connection.

    • In your second example, your connection is acquired and used completely outside of the try-catch construct. If an exception occurs using the connection, it is likely that the whole context will just be tossed out, your finally block will not execute, and your connection will not be closed.

    • In your third example, finally is going to execute after try, but before any code that comes after the finally block. You will generate an exception trying to use the connection, because the connection has already been explicitly closed.