This was an interview question:
public class Demo {
public static void main(String[] args) {
System.out.println(foo());
}
static String foo() {
try {
return "try ...";
} catch (Exception e) {
return "catch ...";
} finally {
return "finally ..."; //got as result
}
}
}
My question is why there are no compile time errors. When I have the return statement in my finally block, it is bound to return from finally instead of try and catch block. I tried to compile this code with -Xlint option, it gives a warning as.
warning: [finally] finally clause cannot complete normally
It does not give a compilation error because it is allowed by the Java Language Specification. However, it gives a warning message because including a return statement in the finally block is usually a bad idea.
What happens in your example is the following. The return statement in the try block is executed. However, the finally block must always be executed so it is executed after the catch block finishes. The return statement occurring there overwrites the result of the previous return statement, and so the method returns the second result.
Similarly a finally block usually should not throw an exception. That's why the warning says that the finally block should complete normally, that is, without return or throwing an exception.
This is described in the Java Language Specification:
§14.17
Abrupt completion of a finally clause can disrupt the transfer of
control initiated by a return statement.
§14.20.2
If execution of the try block completes normally, then the finally
block is executed, and then there is a choice:
If the finally block completes normally, then the try statement completes normally.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S.
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).
There are no compile time error since only 1 and exactly 1 of return statement will actually return the control back to calling code.
As explained #Hoopje, return within try or catch will execute first, their respective return statement will also execute. But just before returning the control back to calling code, it will execute the finally block. Now, this block also returns something, so this return overrides the previous one.
It's essentially the same as this:
public boolean someMethod(){
if(1 == 1){
return true;
}
return false;
}
It will not give a compilation error, although it will give a warning. The compiler will only give an error when there's a chance of no return statement being executed.
Brilliant Question.. According to my knowledge return statement of the try and catch block is transferred to finally if you have added finally block to your code. That's how its work.
So in this case all code lines are executing and you can try debugging. The all three blocks I tried below code.
public class Main {
public static void main(String[] args) {
System.out.println(foo());
}
static String foo() {
try {
throw new Exception();
} catch (Exception e) {
return "catch ...";
} finally {
return "finally ..."; //got as result
}
}
}
You can get the idea from below link.
Multiple returns: Which one sets the final return value?
Your code works fine because there is only one return statement in try, catch and finally blocks. Compilation error will occur if you try to write two return statements inside one of try, catch or finally blocks saying there is an unreachable return statement.
(For short answer- Read the bold and italic parts of the answer)
The execution flow as per the Java 8 docs. It provides you the details. You can infer execution of return statements based on the following.
A try statement with 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 the finally block is
executed, and then there is a choice:
– If the finally block completes normally, then the try statement completes
normally.
– If the finally block completes abruptly for reason S, then the try statement
completes abruptly for reason S.
• 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 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.
Then there is a choice:
› If the catch block completes normally, then the finally block is executed.
Then there is a choice:
» If the finally block completes normally, then the try statement
completes normally.
» If the finally block completes abruptly for any reason, then the try
statement completes abruptly for the same reason.
› If the catch block completes abruptly for reason R, then the finally block
is executed. 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).
– 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 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).
• 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).
the explanation is clear in this link- javaDoc
try running this:
it will print: 1, 2, 3 and then throw a division by zero Exception
public class Demo {
public static void main(String[] args) {
System.out.println(foo());
}
public static String print(int a){
System.out.println(a);
return String.valueOf(a/0);
}
static String foo() {
try {
return print(1);
} catch (Exception e) {
return print(2);
} finally {
return print(3);
}
}
}
Related
This was an interview question:
public class Demo {
public static void main(String[] args) {
System.out.println(foo());
}
static String foo() {
try {
return "try ...";
} catch (Exception e) {
return "catch ...";
} finally {
return "finally ..."; //got as result
}
}
}
My question is why there are no compile time errors. When I have the return statement in my finally block, it is bound to return from finally instead of try and catch block. I tried to compile this code with -Xlint option, it gives a warning as.
warning: [finally] finally clause cannot complete normally
It does not give a compilation error because it is allowed by the Java Language Specification. However, it gives a warning message because including a return statement in the finally block is usually a bad idea.
What happens in your example is the following. The return statement in the try block is executed. However, the finally block must always be executed so it is executed after the catch block finishes. The return statement occurring there overwrites the result of the previous return statement, and so the method returns the second result.
Similarly a finally block usually should not throw an exception. That's why the warning says that the finally block should complete normally, that is, without return or throwing an exception.
This is described in the Java Language Specification:
§14.17
Abrupt completion of a finally clause can disrupt the transfer of
control initiated by a return statement.
§14.20.2
If execution of the try block completes normally, then the finally
block is executed, and then there is a choice:
If the finally block completes normally, then the try statement completes normally.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S.
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).
There are no compile time error since only 1 and exactly 1 of return statement will actually return the control back to calling code.
As explained #Hoopje, return within try or catch will execute first, their respective return statement will also execute. But just before returning the control back to calling code, it will execute the finally block. Now, this block also returns something, so this return overrides the previous one.
It's essentially the same as this:
public boolean someMethod(){
if(1 == 1){
return true;
}
return false;
}
It will not give a compilation error, although it will give a warning. The compiler will only give an error when there's a chance of no return statement being executed.
Brilliant Question.. According to my knowledge return statement of the try and catch block is transferred to finally if you have added finally block to your code. That's how its work.
So in this case all code lines are executing and you can try debugging. The all three blocks I tried below code.
public class Main {
public static void main(String[] args) {
System.out.println(foo());
}
static String foo() {
try {
throw new Exception();
} catch (Exception e) {
return "catch ...";
} finally {
return "finally ..."; //got as result
}
}
}
You can get the idea from below link.
Multiple returns: Which one sets the final return value?
Your code works fine because there is only one return statement in try, catch and finally blocks. Compilation error will occur if you try to write two return statements inside one of try, catch or finally blocks saying there is an unreachable return statement.
(For short answer- Read the bold and italic parts of the answer)
The execution flow as per the Java 8 docs. It provides you the details. You can infer execution of return statements based on the following.
A try statement with 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 the finally block is
executed, and then there is a choice:
– If the finally block completes normally, then the try statement completes
normally.
– If the finally block completes abruptly for reason S, then the try statement
completes abruptly for reason S.
• 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 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.
Then there is a choice:
› If the catch block completes normally, then the finally block is executed.
Then there is a choice:
» If the finally block completes normally, then the try statement
completes normally.
» If the finally block completes abruptly for any reason, then the try
statement completes abruptly for the same reason.
› If the catch block completes abruptly for reason R, then the finally block
is executed. 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).
– 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 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).
• 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).
the explanation is clear in this link- javaDoc
try running this:
it will print: 1, 2, 3 and then throw a division by zero Exception
public class Demo {
public static void main(String[] args) {
System.out.println(foo());
}
public static String print(int a){
System.out.println(a);
return String.valueOf(a/0);
}
static String foo() {
try {
return print(1);
} catch (Exception e) {
return print(2);
} finally {
return print(3);
}
}
}
Here's the code puzzled me:
public Integer getInteger(BlockingQueue<Integer> queue) {
boolean interrupted = false;
try {
while (true) {
try {
return queue.take();
} catch (InterruptedException e) {
interrupted = true;
// fall through and retry
}
}
} finally {
if (interrupted)
Thread.currentThread().interrupt();
}
}
It seems like the try block would not stop because of the While(true) block, but I was told that finally block will always be executed after the try block ends. So When will the finally block execute?
when there's another exception that does not derive from InterruptedException
The finally block will execute when the try block completes, which in your case can be for two reasons:
queue.take() completes normally, which means it returns a value, which causes the return statement to complete normally, and return from the method with the value from take().
queue.take() completes abruptly by throwing an Exception (or Error) other than InterruptedException.
Abbreviated quote of Java Language Specification "Execution of try-finally and try-catch-finally":
If execution of the try block completes normally, then the finally block is executed [...]
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 a catchable exception class of any catch clause [...] Then there is a choice:
If the catch block completes normally, then the finally block is executed [...]
If the catch block completes abruptly for reason R, then the finally block is executed [...]
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 finally block is executed [...]
If execution of the try block completes abruptly for any other reason R, then the finally block is executed [...]
All paths lead to "finally block is executed".
In short, the finally block is always executed when the try block completes, for whatever reason. The only way for that not to happen, is an abnormal termination of the JVM (e.g. JVM kill, JVM crash, OS crash, or power loss).
This question already has answers here:
Multiple returns: Which one sets the final return value?
(7 answers)
Closed 7 years ago.
I found this piece of code in a java certification website
public class Test1{
public static void main(String args[]){
System.out.println(method());
}
public static int method(){
try{
return 1;
}
catch(Exception e){
return 2;
}
finally{
return 3;
}
}
}
So the output of this piece of code is shown as 3.
How is this possible..since it is returning 1 in the try block itself?
The code will never reach finally right??
The code will never reach finally right?
No, If there is a finally block control will go to finally after try or/and catch
Because in any case finally will always execute. Except as Mike Kobit said System.exit
Thanks Jason C, From JLS 14.17. The return Statement
It can be seen, then, that a return statement always completes abruptly.
The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are any try statements (§14.20) within the method or constructor whose try blocks or catch clauses contain the return statement, then any finally clauses of those try statements will be executed, in order, innermost to outermost, before control is transferred to the invoker of the method or constructor. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a return statement.
From JLS 14.20.2. Execution of try-finally and try-catch-finally
If execution of the try block completes normally, then the finally block is executed, and then there is a choice:
If the finally block completes normally, then the try statement completes normally.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S.
So In you code try returns 1, then control goes to finally which returns 3. so return value of function will be 3.
As Sumit Singh mentioned in his answer, this happens because return causes the method to end abruptly.
You can observe the same behaviour, when you throw new Exceptions inside your try-catch-finally block, since throw is also abrupt.
See the following code:
public class FinallyTest {
public static void main(String[] args) {
abrupt();
}
#SuppressWarnings("finally")
public static void abrupt() {
try {
throw new IllegalArgumentException("In Try");
}
catch(Exception x) {
throw new IllegalArgumentException("In Catch");
}
finally {
throw new NullPointerException("In Finally");
}
}
}
When running the code, the console shows
Exception in thread "main" java.lang.NullPointerException: In Finally
at FinallyTest.abrupt(FinallyTest.java:15)
at FinallyTest.main(FinallyTest.java:3)
Even though you throw a new IllegalArgumentException inside the try block, only the NullPointerException from the finally block is thrown, since this block ended abruptly.
Finally block will always get executed just before return statement get executed. (There are some exceptions like JVM itself crash or system.exit() is called)
Here is the reason:
We normally use finally to free up our resources or to cleanup. Now if developer will write return statement accidentally in try block then logically finally would never get executed. To overcome this problem, JVM by itself handle this scenario and execute finally block just before returning from try block.
Remember the finally block always executes when the try block exits. And above explained scenario is also applied to return, continue, or break.
Because if we think about priority finally has more than try or catch, to make it clear what if the exception haven't caught even then the finally executes and here it is working inside a method so logically when a method is suppose to return a single output int value then obviously it will always return values from finally.
Is it makes sense?
Please explain why Exception comes in first program but not in second program.
1) without return statement in read method
class Example
{
public static void read()
{
try
{
int i = 9/0;
}
finally
{
System.out.println("This proogram is giving exception");
}
}
public static void main(String[] fel)
{
read();
}
}
2)with return statement in read method
class Example
{
public static void read()
{
try
{
int i = 9/0;
}
finally
{
System.out.println("This proogram is not giving exception");
return;
}
}
public static void main(String[] fel)
{
read();
}
}
The reason is given in the Java Language Specification rules governing the execution of try/finally blocks. Essentially
if the try block throws an exception E and the finally completes normally then the overall try/finally throws E
if the try block throws E but the finally does not complete normally, then E is ignored and the overall try/finally "completes abruptly" for the reason arising from the finally block
An explicit return is considered abrupt rather than normal completion, so in your example 2 the return inside the finally masks the divide-by-zero exception raised by the try.
Branching statements(return ,goto ) should no be used inside finally because execution of such statement nullifies other instructions which are executed before finally.
The Java Language Specification says : 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 - A return statement inside a finally block will cause any exception that might be thrown in the try or catch block to be discarded.
In both instance, the code with throw a java.lang.ArithmeticException, however the return in the finally discards the exception and instead the method exits without forwarding the exception to the caller.
This is one of the reason why in general you should not use a return in a finally-block.
This is described in the Java Language Specification (8), 14.20.2 Execution of try-finally and try-catch-finally:
If execution of the try block completes abruptly because of a throw of
a value V, then there is a choice:
... (some similar but for this case irrelevant rules left out)
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 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).
You can find the definition of abrupt and normal completion in JLS 14.1 Normal and Abrupt Completion of Statements. But basically a return is considered an abrupt completion.
public class Abc {
public static void main(String args[]) {
System.out.println(Abc.method());
}
static int method() {
try {
throw new Exception();
}
catch(Exception e) {
throw new Exception();
}
finally {
return 4;
}
}
}
Why is the return value 4?
That's the way finally works. The snippet
try {
throw new Exception();
} catch(Exception e) {
throw new Exception();
}
will complete abruptly, but the finally clause will kick in and when it returns it discards the original reason for completing the statement.
This is explained in section Blocks and Statements in the Java Language Specification. I've highlighted the relevant path in your situation:
A try statement with 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 the
finally block is
executed, and then there is a choice:
... 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 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.
Then there is a choice:
If the
catch block completes
normally, then the
finally block is
executed. Then there is a choice:
... If the
catch block completes
abruptly for reason R, then the
finally block is
executed. 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).
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 execution of the
try block completes
abruptly for any other reason
R, then the
finally block is
executed. Then there is a choice:
...
You should never return from a finally block. This is very bad practice. See Java try-finally return design question and Does finally always execute in Java?.
There are several questions on StakOverflow that explain this.
To make it simple: if you put a return or a throw statement in a finally clause this is the last action of your method. Generally speaking this is a bad practice though.
Finally will always return 4. The finally block will always execute regardless of any exception that is throw in the try and catch blocks.
The fact that the finally block returns a value causes the thrown exception to be swallowed, so it wont propagate out of the method.