If I run the following code:
try{
return false;
} catch(Exception e){
e.printStackTrace();
}
finally{
return true;
}
why does it return true?
From the Java Language Specification section 14.20.2
If execution of the try block completes abruptly for any other reason R, then the finally block is executed, and then there is a choice:
If the finally block completes normally, then the try statement completes abruptly for reason R.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
(my italics). A return is one kind of "abrupt completion", in other words the return from the finally overrules the one from inside the try.
It returns true because whenever a finally block completes abruptly, either by return-ing or by throwing an exception, that completion supersedes any previous return-value or exception. (See §14.20.2 "Execution of try-finally and try-catch-finally" in the Java Language Specification, Java SE 7 Edition.)
Because no matter what happens in the try catch portion, the finally block will always do what you ask so in this case it returns true. Just remove the finally statement and it should return false.
Finally block doesnot execute when try or catch block terminate by calling System.exit function. Similarly if the thread executing try catch dies while executing try or catch block then finally block may not execute.
So its likely that your try catch finally block will almost always return true even if your try block is returning false .
Because the finally block will always be executed if a return is encountered.
Related
I have this code:
try {
// if (false) { //(need to add this, otherwise it doesn't compile)
// throw new CountDownExc(-1);
// }
return ad2;
} catch (StackOverflowExc | NoClassDefFoundError e) {
throw new CountDownExc(50);
} catch (CountDownExc e) {
if (!e.surfaced()) {
e.dec();
throw e;
}
return 0.0;
}
And if I don't add the commented code it doesn't compile with a:
error: exception CountDownExc is never thrown in body of corresponding
try statement
Why?
Most of all, why does the first catch doesn't cause the compiler to complain (but the second block seems to be wrong)
There is a couple of problems with your code:
First and foremost you need to understand the difference between checked exceptions and unchecked exceptions: Understanding checked vs unchecked exceptions in Java
Essentially you need to consider checked exceptions as part of your logic and you can only either rethrow them or handle them via catch. The only other option if you need to avoid catch( CountDownExc ) is to add a throws CountDownExc declaration to your method.
These lines make little sense to me:
} catch (StackOverflowExc | NoClassDefFoundError e) {
throw new CountDownExc(50);
It looks like you intend on catching two exception types in the first catch block, throw CountDownExc in that first catch block, then handle it in the second catch block. That's not gonna fly, because catch blocks handle what is thrown in a try block, not in a catch block. Since CountDownExc is a checked exception this is going to result in another compilation error, unless you either wrap your try-catch in another try-catch (bad practice) or add a throws declaration.
See: Exception thrown inside catch block - will it be caught again?
Since both of your catches throw CountDownExc the exception will have to be handled elsewhere anyway, so this may already be accounted for - I cannot tell, because the rest of your code is unknown.
Your immediate problem however comes from the fact, that nothing in your try block is able to throw CountDownExc and CountDownExc is a checked exception, see first link.
try
{
throw tryException();
}
catch
{
throw catchException();
}
finally
{
throw finallyException();
}
According to the official Java Documentation:
"The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs."
See https://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
The finally exception will be thrown except under the condition Suresh Atta has stated in the comments; System.exit() is called, which will abruptly terminate the program.
Remember in the absence of System.exit(), the finally block always runs after the catch block.
As the finally block is ran last, the exception thrown in the finally block will be thrown.
N.B: You can have try, finally block without a catch block.
How much better is:
if (condition) {
try {
//something
} catch(SomeEx ex) {}
}
instead of this:
try {
if (condition) {
//something
}
} catch(SomeEx ex) {}
What actually JVM do when I enter try block ?
EDIT:
I don't want to know that in second example always go in to try... Please answer the question.
Execution wise at run time, as long as there is no exception, try does not cost you anything. It only costs run time as soon as an exception occurs. And in that situation it is much slower that an if evaluation.
In the JVM spec, you see that there is no extra byte code generated on the execution path:
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.12
try {if (condition) {...}} catch(SomeEx ex) {}
Here you handled the exception if it is arised condition of if also if arised inside if-block.
if (condition) {try {...} catch(SomeEx ex) {}}
Here you handle exception if is arised only inside the if-block. If something goes wrong in if condition then it will not be handled.
So it is depends upon the actual senario.
From the perfomance point of view it should be the same. Throwing of the exception is a costly operation (for starters, the stacktrace must be created and populated). The mere existence of the try block has no (or negligible) performance penalty.
See Should java try blocks be scoped as tightly as possible.
What actually JVM do when I enter try block ?
From JLS 14.20.1. Execution of try-catch:
A try statement without a finally block is executed by first executing the try block. Then there is a choice:
If execution of the try block completes normally, then no further action is taken and the try statement completes normally.
If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:
If the run-time type of V is assignment compatible with (§5.2) a catchable exception class of any catch clause of the try statement, then the first (leftmost) such catch clause is selected. The value V is assigned to the parameter of the selected catch clause, and the Block of that catch clause is executed, and then there is a choice:
If that block completes normally, then the try statement completes normally.
If that block completes abruptly for any reason, then the try statement completes abruptly for the same reason.
If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the try statement completes abruptly because of a throw of the value V.
If execution of the try block completes abruptly for any other reason, then the try statement completes abruptly for the same reason.
EDIT:
For a complete Exception description see the JVM 2.10 link in The New Idiot's answer.
If you see oracle docs
>try {
code
}
catch and finally blocks . . .
The segment in the example labeled code contains one or more legal lines of code that could throw an exception.
So,If you feel doubt on your If condition that it will throw an exception put it inside.Otherwise put outside.
if (condition) {
try {
//something
} catch(SomeEx ex) {}
}
is better to use since it executes the try block if the condition is ok.JVM compiles the try block and validated the catch block or a finally block. I think advantage is not in the compile time but in the run time. Compile time I think no advantage at all
Exceptions should be exceptional case , not every time the code runs. So better to check for the condition before trying !
if (condition) {
try {
//something
} catch(SomeEx ex) {}
}
Make sure , if (condition) itself doesn't throws an Exception.
It depends on your usage and functionality . For example this would be better :
if (someObject!=null) {
try {
someObject.getSomething(); // getSomething() potentially throws some Exception
} catch(SomeEx ex) {}
}
What actually JVM do when I enter try block ?
Read JVM spec 2.10.
I'm reviewing some new code. The program has a try and a finally block only. Since the catch block is excluded, how does the try block work if it encounters an exception or anything throwable? Does it just go directly to the finally block?
If any of the code in the try block can throw a checked exception, it has to appear in the throws clause of the method signature. If an unchecked exception is thrown, it's bubbled out of the method.
The finally block is always executed, whether an exception is thrown or not.
A small note on try/finally: The finally will always execute unless
System.exit() is called.
The JVM crashes.
The try{} block never ends (e.g. endless loop).
The Java Language Specification(1) describes how try-catch-finally is executed.
Having no catch is equivalent to not having a catch able to catch the given Throwable.
If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:
If the run-time type of V is assignable to the parameter of any catch clause of the try statement, then …
…
If the run-time type of V is not assignable to the parameter of any catch clause of the try statement, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).
(1) Execution of try-catch-finally
The inner finally is executed prior to throwing the exception to the outer block.
public class TryCatchFinally {
public static void main(String[] args) throws Exception {
try{
System.out.println('A');
try{
System.out.println('B');
throw new Exception("threw exception in B");
}
finally
{
System.out.println('X');
}
//any code here in the first try block
//is unreachable if an exception occurs in the second try block
}
catch(Exception e)
{
System.out.println('Y');
}
finally
{
System.out.println('Z');
}
}
}
Results in
A
B
X
Y
Z
The finally block is always run after the try block ends, whether try ends normally or abnormally due to an exception, er, throwable.
If an exception is thrown by any of the code within the try block, then the current method simply re-throws (or continues to throw) the same exception (after running the finally block).
If the finally block throws an exception / error / throwable, and there is already a pending throwable, it gets ugly. Quite frankly, I forget exactly what happens (so much for my certification years ago). I think both throwables get linked together, but there is some special voodoo you have to do (i.e. - a method call I would have to look up) to get the original problem before the "finally" barfed, er, threw up.
Incidentally, try/finally is a pretty common thing to do for resource management, since java has no destructors.
E.g. -
r = new LeakyThing();
try { useResource( r); }
finally { r.release(); } // close, destroy, etc
"Finally", one more tip: if you do bother to put in a catch, either catch specific (expected) throwable subclasses, or just catch "Throwable", not "Exception", for a general catch-all error trap. Too many problems, such as reflection goofs, throw "Errors", rather than "Exceptions", and those will slip right by any "catch all" coded as:
catch ( Exception e) ... // doesn't really catch *all*, eh?
do this instead:
catch ( Throwable t) ...
Java versions before version 7 allow for these three combinations of try-catch-finally...
try - catch
try - catch - finally
try - finally
finally block will be always executed no matter of what's going on in the try or/and catch block. so if there is no catch block, the exception won't be handled here.
However, you will still need an exception handler somewhere in your code - unless you want your application to crash completely of course. It depends on the architecture of your application exactly where that handler is.
Java try block must be followed by either catch or finally block.
For each try block there can be zero or more catch blocks, but only one finally block.
The finally block will not be executed if program exits(either by calling System.exit() or by causing a fatal error that causes the process to abort).
how does the try block work if it
encounters an exception or anything
throwable
The exception is thrown out of the block, just as in any other case where it's not caught.
The finally block is executed regardless of how the try block is exited -- regardless whether there are any catches at all, regardless of whether there is a matching catch.
The catch blocks and the finally are orthogonal parts of the try block. You can have either or both. With Java 7, you'll be able to have neither!
Don't you try it with that program? It'll goto finally block and executing the finally block, but, the exception won't be handled. But, that exception can be overruled in the finally block!
The finally block is executed after the try block completes. If something is thrown inside the try block when it leaves the finally block is executed.
Inside try block we write codes that can throw an exception.
The catch block is where we handle the exception.
The finally block is always executed no matter whether exception occurs or not.
Now if we have try-finally block instead of try-catch-finally block then the exception will not be handled and after the try block instead of control going to catch block it will go to finally block.
We can use try-finally block when we want to do nothing with the exception.
Regardless of exception thrown or not in try block - finally block will be executed. Exception would not be caught.
I was surprised recently to find that it's possible to have a return statement in a finally block in Java.
It seems like lots of people think it's a bad thing to do as described in 'Don't return in a finally clause'. Scratching a little deeper, I also found 'Java's return doesn't always' which shows some pretty horrible examples of other types of flow control in finally blocks.
So, my question is, can anyone give me an example where a return statement (or other flow control) in a finally block produces better / more readable code?
I had a REALLY hard time to track down a bug years ago that was caused by this. The code was something like:
Object problemMethod() {
Object rtn = null;
try {
rtn = somethingThatThrewAnException();
}
finally {
doSomeCleanup();
return rtn;
}
}
What happened is that the exception was thrown down in some other code. It was being caught and logged and rethrown within the somethingThatThrewAnException() method. But the exception wasn't being propagated up past problemMethod(). After a LONG time of looking at this we finally tracked it down to the return method. The return method in the finally block was basically stopping the exception that happened in the try block from propagating up even though it wasn't caught.
Like others have said, while it is legal to return from a finally block according to the Java spec, it is a BAD thing and shouldn't be done.
The examples you provided are reason enough to not use flow-control from finally.
Even if there's a contrived example where it's "better," consider the developer who has to maintain your code later and who might not be aware of the subtleties. That poor developer might even be you....
javac will warn of return in finally if you use the -Xlint:finally. Originally javac emitted no warnings - if something is wrong with the code, it should fail to compile. Unfortunately backwards compatibility means that unanticipated ingenious foolishness cannot be prohibited.
Exceptions can be thrown from finally blocks, but in that case the exhibited behaviour is almost certainly what you want.
Adding control structures and returns to finally{} blocks are just another example of "just because you can" abuses which are scattered throughout virtually all development languages. Jason was right in suggesting it could easily become a maintenance nightmare - the arguments against early returns from functions apply more-so to this case of "late returns".
Finally blocks exist for one purpose, to allow you to completely tidy up after yourself, no matter what happened in all the preceeding code. Principally this is closing / releasing file pointers, database connections etc., though I could see it being stretched to say adding in bespoke auditing.
Anything that affects the return of the function should lie in the try{} block. Even if you had a method whereby you checked an external state, did a time consuming operation, then checked that state again in case it became invalid, you would still want the second check inside the try{} - if it sat inside finally{} and the long operation failed, you would then be checking that state a second time needlessly.
A simple Groovy Test:
public class Instance {
List<String> runningThreads = new ArrayList<String>()
void test(boolean returnInFinally) {
println "\ntest(returnInFinally: $returnInFinally)"
println "--------------------------------------------------------------------------"
println "before execute"
String result = execute(returnInFinally, false)
println "after execute -> result: " + result
println "--------------------------------------------------------------------------"
println "before execute"
try {
result = execute(returnInFinally, true)
println "after execute -> result: " + result
} catch (Exception ex) {
println "execute threw exception: " + ex.getMessage()
}
println "--------------------------------------------------------------------------\n"
}
String execute(boolean returnInFinally, boolean throwError) {
String thread = Thread.currentThread().getName()
println "...execute(returnInFinally: $returnInFinally, throwError: $throwError) - thread: $thread"
runningThreads.add(thread)
try {
if (throwError) {
println "...error in execute, throw exception"
throw new Exception("as you liked :-)")
}
println "...return 'OK' from execute"
return "OK"
} finally {
println "...pass finally block"
if (returnInFinally) return "return value from FINALLY ^^"
// runningThreads.remove(thread)
}
}
}
Instance instance = new Instance()
instance.test(false)
instance.test(true)
Output:
test(returnInFinally: false)
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: false, throwError: false) - thread: Thread-116
...return 'OK' from execute
...pass finally block
after execute -> result: OK
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: false, throwError: true) - thread: Thread-116
...error in execute, throw exception
...pass finally block
execute threw exception: as you liked :-)
-----------------------------------------------------------------------------
test(returnInFinally: true)
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: true, throwError: false) - thread: Thread-116
...return 'OK' from execute
...pass finally block
after execute -> result: return value from FINALLY ^^
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: true, throwError: true) - thread: Thread-116
...error in execute, throw exception
...pass finally block
after execute -> result: return value from FINALLY ^^
-----------------------------------------------------------------------------
Question:
One interesting point for me was to see how Groovy deals with implicit returns. In Groovy it is possible to "return" from a method simply leaving a value at the end (without return). What do you think happens, if you uncomment the runningThreads.remove(..) line in the finally statement - will this overwrite the regular return value ("OK") and cover the exception?!
Returning from inside a finally block will cause exceptions to be lost.
A return statement inside a finally block will cause any exception that might be thrown in the try or catch block to be discarded.
According to the Java Language Specification:
If execution of the try block completes abruptly for any other reason
R, then the finally block is executed, and then there is a choice:
If the finally block completes normally, then the try statement
completes abruptly for reason R.
If the finally block completes abruptly for reason S, then the try
statement completes abruptly for reason S (and reason R is
discarded).
Note: As per JLS 14.17 - a return statement always completes abruptly.