The finally {}
block is always called (unless you call exit()
before finally is reached - but you won't be doing that most of the time).
The purpose of finally is to clean up any resources allocated in the try {}
block, even if something was thrown and it hit the catch{}
block.
Consider the code:
public class Hello {
public static void main(String[] args) {
hello();
}
public static void hello() {
try {
System.out.println("hi");
return;
} catch (RuntimeException e) {
} finally {
System.out.println("finally");
}
}
}
While there isn't any resource allocation in this, just pretend there is. This will print out:
hi
finally
If you had opened a file in the try block, the finally is the place to clean it up. If you had opened one file, and then tried to open another one (that threw an exception), the finally is the place to clean that up.
If there was an uncaught exception by the catch
block, then the finally
would run, and the exception would get passed on up.
Putting out.close()
in the catch
and the finally
is redundant - because it will be run in the finally block - on a caught exception or successful completion of the try
.
With the existing code, the following code paths are possible:
No exception:
- check() - no exception thrown
- finally { } - out.close
Caught exception:
- check() - MissingParamException thrown
- catch { } - stuff and out.close
- finally { } - out.close
Uncaught exception:
- check() - NPE thrown
- finally { } - out.close
You should be able to see from this, the finally
is always called, and in the caught exception, out.close()
is invoked twice.
The associated spec is ยง14.20.2 in Java SE 7 language specification.
In C++98 there is no guarantee that the internal array is null terminated; in other words string.data()[string.size()]
results in undefined behavior. The implementation will then reallocate the array with the null termination when c_str()
is called but can leave the null terminator off when it isn't.
This also means that &string[0]
is not guaranteed to be null terminated (it is essentially a detour to data()
)
In C++11 the null termination guarantee is specified so string.data()==string.c_str()
is always valid.
Best Answer
try
)catch
)throw
)assert
)finally
)Can't come up with a better description for
finally
than misc transaction-independent control flow. It doesn't necessarily map so directly to any high-level concept in the context of a transaction and error recovery mindset, especially in a theoretical language that has both destructors andfinally
.What's most inherently lacking to me is a language feature that directly represents the concept of rolling back external side effects. Scope guards in languages like D are the closest thing I can think of that comes close to representing that concept. From a control flow standpoint, a rollback in a particular function's scope would need to distinguish an exceptional path from a regular one, while simultaneously automating the rollback implicitly of any side effects caused by the function should the transaction fail, but not when the transaction succeeds. That's easy enough to do with destructors if we, say, set a boolean to value like
succeeded
to true at the end of our try block to prevent the rollback logic in a destructor. But it's a rather roundabout way to do this.While that might seem like it wouldn't save so much, side effect reversal is one of the hardest things to get right (ex: what makes it so difficult to write an exception-safe generic container).