Yes, it is guaranteed.
Say some exception occurred during useCursor(cursor_id)
, now the inner finally block will be executed. (Since the exception happened in the inner try
block). After this genericLogError()
will be called (Since an exception occurred in the outer try
that included the inner try
. And only after it closeDatabasConnection()
will be executed (the finally
of the outer try
). Here is a diagram that might explain it better:
(Exception in the inner try → finally of the inner try ) → this is considered an exception of the outer try → catch of the outer try → finally of the outer try.
You can test it by printing from the blocks.
But why not to do it like this?
try {
useCursor(cursor_id);
} catch(Exception e) {
genericLogError();
} finally {
closeCursor(cursor_id);
closeDatabaseConnection();
}