100

有什么区别

try {
    fooBar();
} finally {
    barFoo();
}

try {
  fooBar();
} catch(Throwable throwable) {
    barFoo(throwable); // Does something with throwable, logs it, or handles it.
}

我更喜欢第二个版本,因为它让我可以访问 Throwable。这两种变体之间是否存在任何逻辑差异或首选约定?

另外,有没有办法从 finally 子句访问异常?

4

11 回答 11

131

这是两个不同的东西:

  • 只有在 try 块中抛出异常时才会执行 catch 块。
  • finally 块总是在 try(-catch) 块之后执行,无论是否抛出异常。

在您的示例中,您没有显示第三种可能的构造:

try {
    // try to execute this statements...
}
catch( SpecificException e ) {
    // if a specific exception was thrown, handle it here
}
// ... more catches for specific exceptions can come here
catch( Exception e ) {
    // if a more general exception was thrown, handle it here
}
finally {
    // here you can clean things up afterwards
}

而且,就像@codeca 在他的评论中所说,没有办法访问 finally 块内的异常,因为即使没有异常,也会执行 finally 块。

当然,你可以在你的块外声明一个保存异常的变量,并在 catch 块内分配一个值。之后,您可以在 finally 块中访问此变量。

Throwable throwable = null;
try {
    // do some stuff
}
catch( Throwable e ) {
    throwable = e;
}
finally {
    if( throwable != null ) {
        // handle it
    }
}
于 2010-05-18T06:17:05.667 回答
14

这些不是变化,它们是根本不同的东西。 始终finally执行,仅在发生异常时执行。catch

于 2010-05-18T06:17:49.910 回答
7

finally 和 catch 块是完全不同的:

  • 在 catch 块中,您可以响应抛出的异常。仅当存在未处理的异常并且类型与 catch 块参数中指定的类型匹配或者是子类时,才会执行此块。
  • finally 将始终在 try 和 catch 块之后执行,无论是否引发异常。

所以

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if ExceptionA 
  // was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in try 
  // and not handled by first catch block
}

不同于

try {
  //some code
}
finally {
  // Gets executed whether or not 
  // an exception was thrown in try block
}

显著地。

如果你定义了一个 try 块,你必须定义

  1. 一个 finally 块,或
  2. 一个或多个 catch 块,或
  3. 一个或多个 catch 块和一个 finally 块

所以下面的代码也是有效的:

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if 
  // ExceptionA was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in 
  // try and not handled by first catch block
}
//even more catch blocks
finally {
  // Gets executed whether or not an 
  // exception was thrown in try block
}
于 2010-05-18T15:12:13.427 回答
5

try用于运行可能抛出异常的方法

catch用于“捕获”停止该异常

finally用于该异常是否被捕获所需的任何清理

try{
    myObject.riskyMethod(); // run a method that may throw an exception
}
catch(Exception ex){
    myLogger.log(ex.Message); // "catch" stop that exception
}
finally{
    myObject = null; // clean up needed from that exception being caught
}
于 2010-05-18T06:17:43.250 回答
3
try {
    statements;
} catch (exceptionType1 e1) {      // one or multiple
    statements;                 
} catch (exceptionType2 e2) {
    statements;
}    
...
} finally {                                 // one or none
    statements;
}
  1. 所有的 try 语句必须包含一个 catch 子句或一个 finally 子句
  2. 它可以有多个 catch 子句但只有一个 finally 子句
  3. 在任何执行过程中,如果发生任何错误,则将 Control 转移到适当的 Catch 块并执行语句并执行 finally 块。

无论如何,始终执行 finally 块,因此通常使用 finally 块,当您有会话、数据库连接或文件或套接字打开时,将放置关闭这些连接的代码。这只是为了确保在应用程序中不会发生内存泄漏或任何其他问题。

于 2010-05-18T07:08:21.563 回答
3

finally 和 catch 块是完全不同的:

在 catch 块中,您可以响应抛出的异常。仅当存在未处理的异常并且类型与 catch 块参数中指定的类型匹配或者是子类时,才会执行此块。finally 将始终在 try 和 catch 块之后执行,无论是否引发异常。

于 2016-02-11T16:01:57.893 回答
2

在我的研究中,Finally 块总是被执行,它主要是“用于关闭任何打开的连接”并破坏不必要的运行。

于 2015-10-14T08:26:24.377 回答
2

通常,当我们使用流、连接等任何资源时,我们必须使用 finally 块显式关闭它们。在下面给出的程序中,我们使用 FileReader 从文件中读取数据,并使用 finally 块关闭它。

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadData_Demo {

   public static void main(String args[]){
      FileReader fr=null;       
      try{
         File file=new File("file.txt");
         fr = new FileReader(file);  char [] a = new char[50];
         fr.read(a); // reads the content to the array
         for(char c : a)
         System.out.print(c); //prints the characters one by one
      }catch(IOException e){
          e.printStackTrace();
       }
       finally{ 
          try{
              fr.close();
          }catch(IOException ex){       
               ex.printStackTrace();
           }
       }
    }

}

也许像我这样的其他人也搜索过类似的东西。

本页信息

于 2016-09-12T08:32:38.107 回答
1

finally 块总是被执行。仅当捕获到与 blocks 参数匹配的异常时,才会执行 Catch 块。

于 2010-05-18T06:18:11.103 回答
1

即使在第一种形式中,您也可以将其记录在调用方法中。因此,除非您想在那里进行一些特殊处理,否则没有太大的优势。

于 2010-08-27T02:36:53.840 回答
0

Try 块将保存将引发异常的语句。catch 块将保存从 try 块抛出的引用,并从 catch 块生成所需的消息。finally 块还用于关闭已使用的资源,例如 io 关闭、文件关闭、dB 关闭。在 Java -9 中,出现了增强的 try-with 资源,其中资源在 try..in 增强的 try 和资源中声明了 catch 块是强制性的

于 2019-09-19T18:06:52.100 回答