1

So, I came across this code and wondered if the compound return statement would fail because the finally block is executed before the return statement is executed :

public DataObject processor(LinkedHashMap itemList)
{
    Extractor ex = DataExtractor.getExtractor();

    try{

        ex.open();

        return ex.processData(itemList);

    }catch(Exception e){

        /* error code */

    }finally{

        if(ex.isOpen()) ex.close();
    }
}

My take is the finally block is executed, closing the Extractor, then the compound return statement is executed, using a closed Extractor, which would result in an error.

Question: Is the compound return statement executed before or after the finally block is executed, resulting in a operation attempted with a closed Extractor?

kermit
  • 1,621
  • 1
  • 14
  • 14
  • finally block will always run at last – Alex Ding Apr 25 '19 at 01:22
  • I think think the `ex.processData(itemList)` is executed first, and the return value saved, then the `finally` clause is executed, then the `return` is executed with the saved value. – markspace Apr 25 '19 at 01:22
  • `return foo();` has no difference from `Object f = foo();return f;` – Ricky Mo Apr 25 '19 at 01:26
  • @markspace if you return a variable name in try block, then if you modify and return variable name in finally block, finally you will get modified name, so you are right. – Alex Ding Apr 25 '19 at 01:28

2 Answers2

3

Is the compound return statement executed before or after the finally block is executed?

The answer is both.

  • Assuming that you don't get an exception prior to that point, ex.processData(itemList); is evaluated before the finally block.

  • The actual return is performed after the finally block.

... resulting in a operation attempted with a closed Extractor?

That won't happen.


The preferred way to implement this is something like the following:

try (Extractor ex = DataExtractor.getExtractor().open()) {
    return ex.processData(itemList);
} catch(SpecificException e) {
    /* error code */
}

Use Java 7+ try with resources, and let that take care of closing the Extractor. And (under most circumstances) don't catch Exception.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0
private static int getInt() {
    int i = 0;
    try(FileInputStream in = new FileInputStream("FILE_PATH")) {
       i = 1;
       return i;
    } catch (Exception e) {
       e.printStackTrace();
    } finally {
       i = 10;
       return i;
    }
}

public static void main(String[] args) {
    System.out.println(getInt()); // print 10 rather than 1
}

method only return once, and the order is fixed, all operation variable located in method stack, return statement will get value in stack and then return it, so if modified the value in finally block, method will always return new value.

Alex Ding
  • 65
  • 8
  • 1
    Above code, gives warning `finally block does not complete normally` as it's not expected to return from finally block [reference](https://stackoverflow.com/questions/17481251/finally-block-does-not-complete-normally-eclipse-warning) – Another coder Apr 25 '19 at 02:15
  • 1
    @Chanchal - Correct. The code / approach in this example should never be used in a real-world application. But the point here is to illustrate the *counter-intuitive* behavior that can occur if you return from inside a `finally` block. – Stephen C Apr 25 '19 at 02:19