Difference between try-finally and try-catch

Finally and catch blocks are quite different:

  • Within the catch block you can respond to the thrown exception. This block is executed only if there is an unhandled exception and the type matches the one or is subclass of the one specified in the catch block's parameter.
  • Finally will be always executed after try and catch blocks whether there is an exception raised or not.

So

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if ExceptionA 
  // was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in try 
  // and not handled by first catch block
}

differs from

try {
  //some code
}
finally {
  // Gets executed whether or not 
  // an exception was thrown in try block
}

significantly.

If you define a try block you have to define

  1. one finally block, or
  2. one or more catch blocks, or
  3. one or more catch blocks and one finally block

So the following code would be valid too:

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if 
  // ExceptionA was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in 
  // try and not handled by first catch block
}
//even more catch blocks
finally {
  // Gets executed whether or not an 
  // exception was thrown in try block
}

These are two different things:

  • The catch block is only executed if an exception is thrown in the try block.
  • The finally block is executed always after the try(-catch) block, if an exception is thrown or not.

In your example you haven't shown the third possible construct:

try {
    // try to execute this statements...
}
catch( SpecificException e ) {
    // if a specific exception was thrown, handle it here
}
// ... more catches for specific exceptions can come here
catch( Exception e ) {
    // if a more general exception was thrown, handle it here
}
finally {
    // here you can clean things up afterwards
}

And, like @codeca says in his comment, there is no way to access the exception inside the finally block, because the finally block is executed even if there is no exception.

Of course you could declare a variable that holds the exception outside of your block and assign a value inside the catch block. Afterwards you can access this variable inside your finally block.

Throwable throwable = null;
try {
    // do some stuff
}
catch( Throwable e ) {
    throwable = e;
}
finally {
    if( throwable != null ) {
        // handle it
    }
}

These are not variations, they're fundamentally different things. finally is executed always, catch only when an exception occurs.