Also, although it's bad practice, if there is a return statement within the finally block, it will trump any other return from the regular block. That is, the following block would return false:
try { return true; } finally { return false; }
Same thing with throwing exceptions from the finally block.
Finally is always run that's the whole point, just because it appears in the code after the return doesn't mean that that's how it's implemented. The Java runtime has the responsibility to run this code when exiting the try block.
For example if you have the following:
int foo() {
try {
return 42;
}
finally {
System.out.println("done");
}
}
The runtime will generate something like this:
int foo() {
int ret = 42;
System.out.println("done");
return 42;
}
If an uncaught exception is thrown the finally block will run and the exception will continue propagating.
In addition to the point about return in finally replacing a return in the try block, the same is true of an exception. A finally block that throws an exception will replace a return or exception thrown from within the try block.