web-dev-qa-db-ger.com

Wie funktioniert return in try, catch und schließlich in Java?

Ich kann nicht genau verstehen, wie return in try, catch funktioniert.

  • Wenn ich try und finally ohne catch habe, kann ich return in den try-Block einfügen.
  • Wenn ich try, catch, finally habe, kann ich return nicht in den try-Block einfügen.
  • Wenn ich einen catch-Block habe, muss ich die return außerhalb der try, catch, finally-Blöcke platzieren.
  • Wenn ich den catch-Block und throw Exception lösche, kann ich die return in den try-Block einfügen.

Wie arbeiten sie genau? Warum kann ich die return nicht in den try-Block einfügen?

Code mit 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 mit try, finally ohne 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);
     }
 }
27
elvis

Ja, das ist verwirrend.

In Java müssen all Programmsteuerpfade einer Nicht-void-Funktion müssen mit einem return enden oder eine Ausnahme auslösen. Das ist die Regel schön und einfach.

In einem Abscheulich erlaubt Java jedoch, einen extra return in einen finally-Block einzufügen, der jeden zuvor angetroffenen return überschreibt:

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

Und wenn ich es versucht habe, fange ich endlich, kann ich return nicht in den try-Block setzen.

Das kannst du absolut. Sie müssen nur sicherstellen, dass jeder Steuerpfad in Ihrer Methode ordnungsgemäß terminiert ist. Damit meine ich: Jeder Ausführungspfad durch Ihre Methode endet entweder in einem return oder in einem throw.

Zum Beispiel funktioniert Folgendes:

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

Hier gibt es zwei mögliche Ausführungspfade:

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

Pfad (1, 2) wird verwendet, wenn foo keine Ausnahme auslöst. Pfad (1, 3) wird verwendet, wenn eine Ausnahme ausgelöst wird. Beachten Sie, wie in beiden Fällen der Block finally ausgeführt wird bevor die Methode verlassen wird.

10
Konrad Rudolph

Schließlich wird block immer ausgeführt, auch wenn die Ausnahme im catch-Block oder sogar unser try-Block wie erwartet abgefangen wurde.

also wann wird endlich block mit im flow ausgeführt ...

wenn wir return Anweisung im try/catch-Block haben dann vor Ausführung der return-Anweisung finally-Block wird ausgeführt (wie beim Schließen der Verbindung oder der E/A)

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

wenn Sie jedoch eine return - Anweisung in der finally-Anweisung haben, wird sie die return-Anweisung im try- oder catch-Block überschreiben.

4
pramesh

Dies ist ein normaler Programmablauf, wenn eine Ausnahmebehandlung beteiligt ist. Wenn der catch-Block im Code ist, entsteht ein Fall, in dem der Codepfad direkt in den catch-Block springen kann. Dies widerspricht dem Mandat, eine return-Anweisung in der Methode zu haben, die etwas zurückgibt. Es ist möglich, dass die return-Anweisung nicht ausgeführt wird, wenn eine Ausnahme auftritt. Daher gibt der Compiler einen Fehler aus. Um dieses Problem zu vermeiden, benötigen Sie mindestens eine weitere return-Anweisung in einer Methode. 

Wenn Sie in try-finally-Block eine return-Anweisung hinzugefügt haben und keinen catch-Block haben, ist dies in Ordnung. Es gibt hier keinen Fall eines abnormalen Codepfads.

Wenn Sie im try-Block eine return-Anweisung hinzugefügt haben und catch-Block haben, können Sie entweder return im catch-Block oder am Ende der Methode hinzufügen. 

Wenn Sie im try-Block eine return-Anweisung hinzugefügt haben und catch-Block und finally-Block haben, können Sie entweder return im catch-Block oder am Ende der Methode hinzufügen. Sie können auch auswählen, ob Sie den Zeilenumbruch im Endeffekt hinzufügen möchten. Wenn Sie Eclipse verwenden, wird eine Warnung generiert, die mit der folgenden Methodendefinition unterdrückt werden kann. 

@SuppressWarnings("finally")
0
user8235810