How does return work in try, catch, finally in Java?

11,952

Solution 1

Yes, it's confusing.

In Java, all program control paths of a non-void function must finish with a return, or throw an exception. That's the rule put nice and simply.

But, in an abomination, Java allows you to put an extra return in a finally block, which overrides any previously encountered return:

try {
    return foo; // This is evaluated...
} finally {
    return bar; // ...and so is this one, and the previous `return` is discarded
}

Solution 2

Finally block will always execute even if we caught the exception in catch block or even our try block executed as expected.

so when does finally block will be execute with in the flow...

if we have return statement inside the try/catch block then before executing the return statement finally block will be executed (like as for closing the connection or I/O)

function returnType process() {
  try {
      // some other statements
      // before returning someValue, finally block will be executed
      return someValue;
  } catch(Exception ex) {
     // some error logger statements
     // before returning someError, finally block will be executed
     return someError;
  } finally {
    // some connection/IO closing statements
    // if we have return inside the finally block
    // then it will override the return statement of try/catch block
    return overrideTryCatchValue;
  }
}

but if you have return statement inside the finally statement then it will override the return statement inside the try or catch block.

Solution 3

And if I have try, catch, finally I can't put return in the try block.

You absolutely can. You just need to make sure that every control path in your method is terminated properly. By that I mean: every execution path through your method either ends in a return, or in a throw.

For instance, the following works:

int foo() throws Exception { … }

int bar() throws Exception {
    try {
        final int i = foo();
        return i;
    } catch (Exception e) {
        System.out.println(e);
        throw e;
    } finally {
        System.out.println("finally");
    }
}

Here, you’ve got two possible execution paths:

  1. final int i = foo()
  2. either
    1. System.out.println("finally")
    2. return i
  3. or
    1. System.out.println(e)
    2. System.out.println("finally")
    3. throw e

Path (1, 2) is taken if no exception is thrown by foo. Path (1, 3) is taken if an exception is thrown. Note how, in both cases, the finally block is executed before the method is left.

Share:
11,952
elvis
Author by

elvis

I like Java and Blockchain

Updated on June 15, 2022

Comments

  • elvis
    elvis almost 2 years

    I can't understand exactly how return works in try, catch.

    • If I have try and finally without catch, I can put return inside the try block.
    • If I have try, catch, finally, I can't put return in the try block.
    • If I have a catch block, I must put the return outside of the try, catch, finally blocks.
    • If I delete the catch block and throw Exception, I can put the return inside the try block.

    How do they work exactly? Why I can't put the return in the try block?

    Code with try, catch, finally

     public int insertUser(UserBean user) {
         int status = 0;
    
         Connection myConn = null;
         PreparedStatement myStmt = null;
    
         try {
             // Get database connection
             myConn = dataSource.getConnection();
    
             // Create SQL query for insert
             String sql = "INSERT INTO user "
                        + "(user_name, name, password) "
                        + "VALUES (?, ?, ?)";
    
             myStmt = myConn.prepareStatement(sql);
    
             // Set the parameter values for the student
             myStmt.setString(1, user.getUsername());
             myStmt.setString(2, user.getName());
             myStmt.setString(3, user.getPassword());
    
             // Execute SQL insert
             myStmt.execute();
         } catch (Exception exc) {
             System.out.println(exc);
         } finally {
             // Clean up JDBC objects
             close(myConn, myStmt, null);
         }
    
         return status;
     }
    

    Code with try, finally without catch

     public int insertUser(UserBean user) throws Exception {
         int status = 0;
    
         Connection myConn = null;
         PreparedStatement myStmt = null;
    
         try {
             // Get database connection
             myConn = dataSource.getConnection();
    
             // Create SQL query for insert
             String sql = "INSERT INTO user "
                        + "(user_name, name, password) "
                        + "VALUES (?, ?, ?)";
    
             myStmt = myConn.prepareStatement(sql);
    
             // Set the parameter values for the student
             myStmt.setString(1, user.getUsername());
             myStmt.setString(2, user.getName());
             myStmt.setString(3, user.getPassword());
    
             // Execute SQL insert
             myStmt.execute();
    
             return status;
         } finally {
             // Clean up JDBC objects
             close(myConn, myStmt, null);
         }
     }