Multiple return statements without compiler error

JavaCompiler ErrorsReturnTry CatchTry Catch-Finally

Java Problem Overview


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

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

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).

Solution 3 - Java

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.

Solution 4 - Java

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. https://stackoverflow.com/questions/2309964/multiple-returns-which-one-sets-the-final-return-value

Solution 5 - Java

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.

Solution 6 - Java

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.

Solution 7 - Java

(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

Solution 8 - Java

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);
    }
  }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2575725View Question on Stackoverflow
Solution 1 - JavaHoopjeView Answer on Stackoverflow
Solution 2 - JavaDragan BozanovicView Answer on Stackoverflow
Solution 3 - JavaAakashView Answer on Stackoverflow
Solution 4 - JavaLasitha BenaragamaView Answer on Stackoverflow
Solution 5 - JavaRoel StrolenbergView Answer on Stackoverflow
Solution 6 - JavathanujaView Answer on Stackoverflow
Solution 7 - JavaTejus PrasadView Answer on Stackoverflow
Solution 8 - JavaJens TimmermanView Answer on Stackoverflow