Как работает возврат в try, catch, наконец, в Java?

Я не могу точно понять, как работает return в try, catch.

  • Если я try и, finally не catch, я могу return внутри блока try.
  • Если я try, catch, finally, я не могу поместить return в блок try.
  • Если у меня есть блок catch, я должен поместить return за пределы блоков try, catch, finally.
  • Если я удалю блок catch и throw Exception, я могу поместить его return в блок try.

Как они работают точно? Почему я не могу поместить return в блок try?

Код с 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;
 }

Код с try, finally без 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);
     }
 }

Ответ 1

Да, это сбивает с толку.

В Java все пути управления программой функции non- void должны заканчиваться return или вызывать исключение. То, что правило ставило хорошо и просто.

Но, в мерзости, Java позволяет вам добавить дополнительный return в блок finally, который переопределяет любой ранее встреченный return:

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

Ответ 2

И если я попытаюсь, поймаю, я не смогу вернуть return в блок try.

Вы абсолютно можете. Вам просто нужно убедиться, что каждый путь управления в вашем методе завершен правильно. Под этим я подразумеваю: каждый путь выполнения через ваш метод заканчивается либо return, либо throw.

Например, следующие работы:

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

Здесь у вас есть два возможных пути выполнения:

  1. final int я = foo()
  2. или
    1. System.out.println("finally")
    2. return i
  3. или же
    1. System.out.println(e)
    2. System.out.println("finally")
    3. throw e

Путь (1, 2) берется, если исключение не выбрано foo. Путь (1, 3) берется, если выбрано исключение. Обратите внимание, что в обоих случаях блок finally выполняется до того, как метод оставлен.

Ответ 3

Наконец, блок всегда будет выполняться, даже если мы поймаем исключение в блоке catch или даже наш блок try выполним, как ожидалось.

поэтому, когда окончательный блок будет выполняться с потоком...

если у нас есть оператор return внутри блока try/catch, то перед выполнением оператора return окончательный блок будет выполнен (например, для закрытия соединения или ввода-вывода)

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

но если у вас есть оператор return внутри выражения finally, то он переопределит оператор return внутри блока try или catch.

Ответ 4

Это нормальный поток программ при обработке исключений. Наличие блокировки в коде создает случай, когда путь кода может напрямую входить в блок catch. Это наносит ущерб мандату с возвратом в методе, который возвращает что-то. Возможно, что оператор return не может быть выполнен, если возникает исключение, поэтому компилятор выдает ошибку. Поэтому, чтобы избежать этой проблемы, вам понадобится как минимум еще один оператор return в методе.

Если вы добавили оператор return в блок try-finally, и у вас нет блокировки catch, это нормально. Здесь нет случая аномального кода.

Если вы добавили оператор return в блок try и у вас есть catch block, вы можете либо добавить return в catch catch, либо в конце метода.

Если вы добавили оператор return в блок try и у вас есть блок catch и, наконец, блокируете, то вы можете либо добавить возврат в блок catch, либо в конце метода. Вы также можете добавить возврат в блок finally. Если вы используете eclipse, он будет генерировать предупреждение, которое может быть подавлено, используя приведенное выше определение метода -

@SuppressWarnings("finally")

Ответ 5

Я думаю, это то, о чем вы спрашиваете:

И если я попытаюсь, поймаю, я не смогу вернуть return в блок try.

Поэтому, если вы добавите блок catch, вы не можете поместить return в блок try.

Проблема в том, что если вы добавляете catch управление переходит через, и вам нужно return в конце метода или это синтаксическая ошибка. Я не тестировал это, но я предполагаю, что вы могли бы поместить return в блок try, но вам также нужно будет добавить его внутри catch или в конце метода, как сейчас.

Ответ 6

Во втором примере, если проверенное исключение происходит, оно переходит к вызову метода.

В первом примере, если проверенное исключение происходит, оно обрабатывается одним и тем же методом, поскольку блок catch берет на себя ответственность за обработку исключения.

если вы пишете оператор return в блоке catch, то он работает.
т.е.

try{  
    return ..  
}catch(Exception e){  
    return ..  
}finally{  
}

Но это не хорошая практика программирования.

Ответ 7

При использовании публичных функций, отличных от функций void, вы должны вернуть что-то или ваша функция не будет.