flow-control in finally block when catching exceptions ,are authorised , yes it's authorized in JAVA but a very bad authorization,especially when you return something from such as
finally{
return something
}
It can prevent dspatching of exception in try ,
let’s see with this code :
public someType loadUserContext(){
try {
// some operation
} catch (IOException e) {
}finally {
return someType; ➪ considered as a ❝complete abruptly❞ statement
}
}
Take a look at JAVA documentation here saying :
❝If the finally block completes abruptly for reason S, then the try
statement completes abruptly for reason S (and reason R is
discarded).❞. Link below:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.2
A return statement is considered as a "complete abruptly" so the result is Exception (if happens)
is not dispatched from try bloc and this is a nig issue and hard to track sometimes.
What does mean Exception Dispatching?
Exception is in reality a mechanism of processor , called interruption , when something is wrong during processing a task , processor interrupt the current execution and instead It execute a specific routine which is called Exception Handler (for example a divide by zero or any other wrong calculation) OS take advantage of this mechanism and implements all kind of Exception Handling based on this processor behaviour then expose a set of API to developers in order to use and be notified when something is wrong .
DEMO:
Dispatching here is to let OS about the wrong operation and OS in turn notify other app about this , in any case OS should be bridge between you and Exception Handler , if OS can’t any more catch an Exception or not being aware about what happen , other apps ore components will be impacted , when you do a Control-Flow operation like return in finally , even if there is an Exception occurs in try bloc , this exception is not dispatched to OS !!!! and it’s dangerous because this exception cannot be communicated to other parts of your components (for example suppose you have a module “Exception Manager” )That’s the point I want to talk
To understand better this issue , create a class which have only try an finally bloc like this
class FinallyChecker {
public boolean doSomeThing() {
try {
throw new IllegalStateException();
} finally {
System.out.println("Finally is executed");
return true;
}
}
}
Now try somewhere in your code to call FinallyChecker’s doSomeThing method in order to explicitly provoque an IllegalStateException , like the following codes
FinallyChecker fc = new FinallyChecker();
fc.doSomeThing();
Surprise!!!! IllegalStateException is not raised and your code continue to run normally without any problem!!!
The reason is because finally complete abruptly (reason R) and Try (reason S) is ignored ,so not dispatched to system !!
Notice : This behaviour is not impacting the current Thread , for example if you add a catch bloc , it's working as expected see this code:
class FinallyChecker {
public boolean doSomeThing() {
try {
throw new IllegalStateException();
} catch(IllegalStateException ex){
System.out.println("IllegalStateException is raised");
} finally{
System.out.println("Finally is executed");
return true;
}
}
}
if you see the logs now everything is fine in current Thread and you will see logs are printed :
IllegalStateException is raised
Finally is executed
The following diagram show the scenario
When catch is present the program continue its execution as expected , if catch is not present system looks for finally if it complete abruptly it continue as well without reporting anything
But still system is unaware about every thing so for conclusion I think we should avoid to put Control-Flow operation
such as return, break,continue,...etc in finally bloc
Thanks
Khosrov July 06 , 2017