Java 中的finally 块的要点是什么?

发布于 2024-09-07 19:10:16 字数 402 浏览 2 评论 0原文

我思考以下例子;但无法弄清楚finally块的重要性是什么。您能告诉我这两个代码示例的执行有何不同吗?现实生活中的例子也会有所帮助。

样品 1:

    try{
       // some code 1
    }catch(Exception ex){
       // print exception   
    }finally{
       // some code 2            
    }

样品 2:

    try{
      // some code 1
    }catch(Exception ex){
      // print exception   
    }
    // some code 2

I think on the following examples; but could not figure out what the importance of the finally block is. Can you tell me the difference of the executions of these two code samples? Also a real life example can be helpful.

Sample 1:

    try{
       // some code 1
    }catch(Exception ex){
       // print exception   
    }finally{
       // some code 2            
    }

Sample 2:

    try{
      // some code 1
    }catch(Exception ex){
      // print exception   
    }
    // some code 2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

睫毛上残留的泪 2024-09-14 19:10:16

您提供的两个片段存在很大差异,例如,当 catch 块本身引发异常时,finally 块仍将按其语义执行。

下面的代码片段会打印 "Finally!",但不会打印 "What about me???"

    try {
        throw null;     // throws NullPointerException!
    } catch (Exception e) {
        int oops = 1/0; // throws ArithmeticException!
    } finally {
        System.out.println("Finally!"); // still gets executed!
    }
    System.out.println("What about me???"); // doesn't get executed!

一般来说,a 的 finally try实际上总是 被执行。对于 try 块后面的任何代码都没有这样的保证。


但是如果我的 catch 块只是一个简单的 print 语句怎么办?

仍然不能保证它不会抛出某些东西。在例如异常详细消息的构造中,仍然可能会出现问题。

即使您尽最大努力保证 catch 代码是“安全的”并且 try 语句后面的代码始终会被执行,问题也变成了“为什么?” 。为什么要避免 finally 但又如此努力地复制它的语义?

finally 语义得到保证,不需要代码的编写者或读者提供举证责任。正因为如此,使用 finally 块来放置强制“清理”代码是惯用的。使用finally可以保证正确性并增强可写性和可读性。

There is a big difference in the two snippets you've presented, e.g. when the catch block itself throws an exception, the finally block would still be executed by its semantics.

That is the following snippet prints "Finally!", but not "What about me???":

    try {
        throw null;     // throws NullPointerException!
    } catch (Exception e) {
        int oops = 1/0; // throws ArithmeticException!
    } finally {
        System.out.println("Finally!"); // still gets executed!
    }
    System.out.println("What about me???"); // doesn't get executed!

Generally speaking, the finally of a try block practically always gets executed. There's no such guarantee for any code following the try block.


But what if my catch block is just a simple print statement?

There's still no guarantee that it won't throw something. Something could still go wrong in e.g. the construction for the exception detailed message.

Even if you make a best effort guarantee that the catch code is "safe" and the code following the try statement will always be executed, the question then becomes "Why?". Why avoid finally but then try so hard to replicate its semantics?

finally semantics is guaranteed, requiring no burden of proof from either the writer or the reader of the code. Precisely because of this, it's idiomatic to use finally block to put mandatory "clean-up" code. Using finally guarantees correctness and enhance both writability and readability.

眼波传意 2024-09-14 19:10:16

即使抛出 Errorfinally 块也会被执行,而在您的示例中,该错误未被 catch 块捕获。因此,您可以将清理代码放在 finally 块中,该代码应该始终运行,无论 try中的操作结果如何。 code>catch 块。

请注意,通常 catch 块会捕获更特定类型的异常 - 通常仅检查异常 - 因此在大多数情况下,上面两个代码示例之间的差异非常明确。

更新:你可能会说你的catch块永远不会抛出异常,所以不需要finally。但是,请注意两件事:

  • 这只是代码的当前状态,并且将来可能会发生变化 - 您能否保证未来的程序员在中添加一些可能引发异常的代码>catch 块,是否记得将其后面的清理代码放入 finally 块中?
  • try-catch-finally 是一种编程习惯,它使阅读代码的人更容易理解发生了什么。如果您不使用常见的习惯用法,则可能会产生误解,从而长期存在错误。

The finally block is executed even if e.g. an Error is thrown, which is not caught by the catch block in your example. So you can put cleanup code in the finally block, which should be run always, regardless of the outcome of the operations in the try and catch blocks.

Note that usually catch blocks catch more specific types of exceptions - often only checked exceptions -, so in most cases the difference between the two code examples above is very definite.

Update: you may say that your catch block can never throw an exception, so finally is not needed. However, note two things:

  • this is only the current state of the code, and it can change in the future - can you guarantee that the future programmer who adds some potentially exception-throwing code in the catch block, will remember to put the cleanup code after it into a finally block?
  • try-catch-finally is a programming idiom which makes it easier for people reading the code to understand what's going on. If you don't use the common idiom, you risk misunderstanding, thus bugs on the long term.
念﹏祤嫣 2024-09-14 19:10:16

您可以使用finally 块来清理和运行任何应该运行的代码,无论是否引发(并捕获)异常。这包括 catch 块中的代码。

You use the finally block in order to cleanup and run any code that should run whether an exception was thrown (and caught) or not. This includes code that you have in the catch block.

妄想挽回 2024-09-14 19:10:16

当我们想要释放 try 块中使用的资源时,它很有帮助。因此,执行它们而不会在任何情况下丢失的唯一位置是finally 块。因为如果抛出异常,java不会执行紧随其后的代码。它直接跳转到catch块。

it is helpful when we want to free up the resources we used in try block. So the only place to execute them without missing at any case is finally block. Since if exception is thrown, java does not execute code which immediate after that. it directly jump to the catch block.

可遇━不可求 2024-09-14 19:10:16

请注意,您甚至可以在没有 catch 的情况下使用 try-finally:

try{
   // some code 
}finally{
   // cleanup code
}

因此,一个示例可能是想要将异常传播给调用者的方法,但仍然需要清理代码,例如释放外观。

Note that you can have even try-finally without a catch:

try{
   // some code 
}finally{
   // cleanup code
}

An example therefore could be a method that wants to propagate exceptions to the caller, but still needs clean up code, like releasing a look.

东风软 2024-09-14 19:10:16

如果 try 块中的语句抛出未经检查的异常,finally 块将被执行,允许程序员采取相关操作。

In case where the statements in try block throw unchecked exceptions, finally block will get executed allowing programmer to take relevant actions.

橘亓 2024-09-14 19:10:16

在现实生活中,即使发生异常,finally 块也用于关闭打开的资源。
例如,当您读取(或写入)文件时、访问数据库时等。

public void readFile(String fileName) {
    FileReader fr;
    BufferedFileReader bfr;

    try {
        fr = new FileReader(fileName);
        bfr = new BufferedFileReader(fr);
        // ...
    } catch (IOException ioe) {
        // ...
    } finally {
        // TO ENSURE THAT THE READERS ARE CLOSED IN ALL CASES
        if (bfr != null) { 
            try {
                bfr.close();
            } catch (IOException ignoredIOE) {}
        }
        if (fr != null) { 
            try {
                fr.close();
            } catch (IOException ignoredIOE) {}
        }
    }
}

In real life, the finally block is used to close opened resources even if an exception occurs.
For example, when you read (or write) a file, when you access to a database, etc.

public void readFile(String fileName) {
    FileReader fr;
    BufferedFileReader bfr;

    try {
        fr = new FileReader(fileName);
        bfr = new BufferedFileReader(fr);
        // ...
    } catch (IOException ioe) {
        // ...
    } finally {
        // TO ENSURE THAT THE READERS ARE CLOSED IN ALL CASES
        if (bfr != null) { 
            try {
                bfr.close();
            } catch (IOException ignoredIOE) {}
        }
        if (fr != null) { 
            try {
                fr.close();
            } catch (IOException ignoredIOE) {}
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文