java try catch finally - return [duplicate] - java

This question already has answers here:
try and Finally giving exception with no return statement , but there is no exception when return statement is written in method
(3 answers)
Closed 8 years ago.
Trying out a try catch finally use case -
public class Finallyy {
public static void main(String[] args) {
int result = method1();
System.out.println(result);
}
private static int method1() {
int a = 2;
try {
int b = 0;
a = a / a;
System.out.println("try");
return a;
} catch (Exception e) {
System.out.println("caught");
a = 5;
return a;
}
finally {
System.out.println("finally");
a = 10;
return a;
}
}
}
Output:
try
finally
10
If the code is modified to
finally {
System.out.println("finally");
a = 10;
//return a;
}
Output:
try
finally
1
Question - Is there some concept of stack where the 'return a' in try block is stored [if the example is altered, then it applies to try or catch block], and popped when control leaves the method1() only in the absence of a 'return' in finally block ?
Update: Solution concluded:
When the return statement is executed, the value to be returned is stored. When the finally block completes, that value is returned.
The finally block gets always executed as last. So the return in the finally block OVERWRITES the other returns in the try/catch blocks. It's a very bad practice to return or throw an exception from the finally block for this reason.
So to the original question - is it only in the absence of a 'return' in finally block ? NO. It doesn't matter.
Edit:
This question is asked on Apr 8 and is answered already. The question that is currently marked along with this as duplicate, is one asked at a later date [August 15]. Hence the new question is to be marked as duplicate, and not this one. However sharing the referenc eto a similar question is good.

A try block is executed before its finally block.
When the return statement is executed, the value to be returned is stored. When the finally block completes, that value is returned.
Note that a is not a value. a is a variable that stores a value. If you change a, you change a, you don't change the value that was stored for the return.
For the technical reason, we go to the Java Language Specification on the try-finally block
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).
A return statement completes abruptly, so if a try with a finally has a return and the finally also has a return, the finally's return supersedes the try's.

The finally block gets always executed as last. So the return in the finally block OVERWRITES the other returns in the try/catch blocks.
It's a very bad practice to return or throw an exception from the finally block for this reason.
Nothing to do with stacks: it's a matter of the fact that the finally block gets always executed as last block, so what is returned or thrown in the finally block erases and overwrites any previous exit value (returned object or exception thrown).
Try this:
try {
throw new NullPointerException();
}
finally {
return 0;
}
The return in the finally block will overwrite (swallow) the NullPointerException...

A try..catch..finally is actually compiled as a nested try..catch (of the exception you specify) within a try..catch (of "any"), and the "finally" block is cut & pasted by the compiler to the "end" of each code path. (I put "end" in quotes because I can't remember off the top of my head how it handles multiple exits from a "try" or "catch" block.) You can use the javap command (dis-assembler) to experiment on what byte code is generated by your version of Java to correspond to different try..catch..finally combinations.

Related

If catch statement is returning ,then why it is going to finally block? [duplicate]

This question already has answers here:
Does a finally block always get executed in Java?
(51 answers)
Closed 5 years ago.
package com.ami.practice;
public class UnrechebleStatement {
public static void main(String[] args) {
System.out.println(m());
}
public static int m(){
try{
int x=0;
int y=10/x;
return y;
}catch(Exception e){
return 1;
}finally {
return 2;
}
}
}
from the JLS#14.17
A return statement with an Expression attempts to transfer control to the invoker of the method that contains it; the value of the Expression becomes the value of the method invocation. More precisely, execution of such a return statement first evaluates the Expression. If the evaluation of the Expression completes abruptly for some reason, then the return statement completes abruptly for that reason. If evaluation of the Expression completes normally, producing a value V, then the return statement completes abruptly, the reason being a return with value V.
[...]
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.
Especially the second part should perfectly answer your question
Finally block is always executed... Wether try is executed or catch...
Finally is always called except in some cases
1) if System.exit() is called
2) if jvm crashes
3) if we use nested try catch

try/finally without catch with return statement? [duplicate]

This question already has answers here:
Multiple returns: Which one sets the final return value?
(7 answers)
Closed 7 years ago.
Why the result of the following code is 3, why the finally get to terminate and get out of the method even tho the compiler checks try first and why the return in try doesn't terminate the method?
public int returnVal(){
try{
return 2;
}
finally{
return 3;
}
}
See JLS 14.17
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.
Espacially check the phrases attempts to transfer control and the last sentence. The try return attempts to transfer the controll, aftwerwards the finally disrupt the transfer of control initiated by a return statement.
In other words, the try attempts to transfer the controll, but since the execution of the finally block is still open for execution and contains a return statement the attempted transfer of controll in the finally block has a higher preceding. That´s why you see the value 3, which is returned inside the finally block.
finally is executed before returning value from try (or catch).
If in the finally a return statement is present it overwrites the return of the try (or catch) block.
So also in this case the return of finally wins:
try {
// Exception thrown
return 2;
} catch (Exception e) {
return 1;
} finally {
return -1; // Always returns -1 also if a return statement is present in the try and in the catch clause
}
Why the return in try doesn't terminate the method?
Is it bad practice to return from within a try catch finally block?
You have to be aware that when you put a return inside a try-catch statement, the return itself is held and managed by the exeption handling block.
The exception block only STORES your return and it really returns it ONLY after all the verifications are done, which doesn't mean that the finally block will really have an impact on your return:
public int returnVal() {
int i = 0;
try {
return i;
}
finally {
i = 99;
}
}
In this case, the return will still be 0.
But in the case you mentioned in your question, you affect the return a second time, and as the exception block dosen't want to let your return go until it's done with ALL its verification, you're just always storing a return value 2 times in your exception block. The result will always be 3.
Just keep in mind that if you put a return inside a try-catch-finally, that return will not return until the finaly block has run; the return itself is just being stored until everything has been verified.
finally explication when you write a finnaly block these always execute it.
The finally block is always executed before control is returned to the calling function.
So in this case before returning 2, it will call finally and will return 3.

Java - If I return in a catch block, will the finally block be executed? [duplicate]

This question already has answers here:
Does a finally block always get executed in Java?
(51 answers)
Closed 9 years ago.
This is what I'm trying to do:
try {
//code
} catch (Exception e) {
return false;
} finally {
//close resources
}
Will this work? Is it bad practice? Would it be better doing this:
boolean inserted = true;
try {
//code
} catch (Exception e) {
inserted = false;
} finally {
//close resources
}
return inserted;
Yes, it will. The only things that can prevent a finally block to execute (AFAIR) are System.exit(), and an infinite loop (and a JVM crash, of course).
The finally block is executed always, unconditionally, as the last thing the try-catch-finally block does. Even if you execute Thread#stop against it, the finally block will still execute, just as if a regular exception ocurred.
Not just that, if you return from finally, that return value will trample over the return from either try or catch.
BTW Your first example is not just fine, but preferred. In the second example the reader must chase around the assignments to the variable, which is a tedious job and lets bugs slip through very easily.
Both are approximately the same. However, be careful with the following case:
int i = 0;
try
{
//code
}
catch(Exception e)
{
return i;
}
finally
{
i = 1;
}
0 is what will be returned.
I just wanted to add that it's described in the specs:
If the catch block completes abruptly for reason R, then the finally block is executed.
where of course
It can be seen, then, that a return statement always completes abruptly.

Should last statement be `return` in and non void return types method?

Should last statement be return in and non void return types method? But this is still working.
public String test()
{
try
{
// Do my work
return "myValue";
}
finally
{
System.out.println("I'm in Finally");
}
}
I'm bit lack of knowledge to understand how this work. Could someone explain me.
There is no problem with this code, because every possible path through it inevitably leads to a return statement*. It does not have to be the last statement textually, as long as it is the last statement logically (Java compiler is smart enough to figure out if it's so, and give you an error if there are paths through your code that do not return a value or throw an exception). The fact that there will be code executing after hitting the return (i.e. your finally block) does not change anything: as far as the compiler is concerned, your function has provided a return value before exiting the function.
* In fact, there is only one path through your function's code, and it terminates at the return statement.
It is sufficient in Java to make sure that all possible code paths either return a value or throw an exception. For example, the following code is valid:
public boolean test() {
if (3 < 5) {
return true;
} else {
throw new RuntimeException("Holy crap!");
}
}
In your example, your try block ends with a return, so the happy path is covered and there is no need for code beyond the finally; in addition, any exceptions thrown in the try will propagate out of the method and will have no chance to reach the end of the method, so all possible paths will never hit the section under the finally block and no return statement is needed. (In fact, a compiler may give you a warning or error about unreachable code if you added a return statement at the bottom!)
Things change when you add a catch clause, because now it's possible for code to flow beyond the try/catch/finally block:
public String test(){
try{
// Do my work
return "myValue";
}
catch (Exception ex) {
System.out.println("O noes something went wrong");
// swallow exception
}
finally {
System.out.println("I'm in Finally");
}
// Oh no! If an exception was caught, code can actually flow through here.
// Compiler will complain about a missing return statement until you add one.
// return "someOtherValue";
}
The key JLS concept for this is Normal and Abrupt Completion of Statements, combined with the behavior of try-finally.
The try block completes abruptly because of the return of "myValue". The finally block completes normally, so the whole try statement completes abruptly due to the same cause as the try block, return of "myValue".
In effect, the last statement in the method, the try statement, is one that returns a String.
In this case try and finally always execute. So, it doesn't matter where is return.
public String myfun(){
return "here";
}
or
public String myfun(){
try{
return "here";
}finally{
//will execute always
}
}
Are almost same. When, you see the flow of program. But, if there would be any conditional like
public String myfun(){
if(x==1){
return "here";
}
else{
// something here
}
}
In this case, it will raise error. Since, either any of the block will execute not both. Same as
public String fun(){
try{
return "here";
}
catch(Exception e){
//catch implementation without return
}
}

Why in a try catch finally, the return is always that of finally?

What happens to the return A code in my catch block?
public class TryCatchFinallyTest {
#Test
public void test_FinallyInvocation()
{
String returnString = this.returnString();
assertEquals("B", returnString);
}
String returnString()
{
try
{
throw new RuntimeException("");
}
catch (RuntimeException bogus)
{
System.out.println("A");
return "A";
}
finally
{
System.out.println("B");
return "B";
}
}
}
The finally get's executed right before any return's / exits from the method. Therefore, when you do
return "A";
it executes like so:
System.out.println("B");//Finally block
return "B";//Finally block
return "A";//Return from exception catch
And thus the "B" is returned, not the "A"
Maybe return "A"; is optimized away by the compiler, maybe not and "A" is just dynamically replaced. In fact it doesn't matter as you should not have this code.
This is one of the classical examples of problems with using finally for control flows : you lose some instructions and another coder might not see the "intent" (in fact it can only be a bug or a mischief).
You may have noted that javac issues a warning "finally block does not complete normally".
Don't return in a finally clause
the finally block will always be executed, while the catch block is only executed if there's an exception caught.
Finally
You can attach a finally-clause to a try-catch block. The code inside the finally clause will always be executed, even if an exception is thrown from within the try or catch block. If your code has a return statement inside the try or catch block, the code inside the finally-block will get executed before returning from the method.
References http://tutorials.jenkov.com/java-exception-handling/basic-try-catch-finally.html
Before return "A" , finally block would be called which will return "B" and your return "A" would be skipped and would never be executed. Its because finally block is always executed before return statement of the method, and if you are returning something from finally block then the return statement of your try/catch would always skipped.
Note : Returning from finally block is not a good practice for a Java programmer. JAVA Compiler also show you the warning as "finally block does not complete normally" if you are returning something from finally block.

Categories