【问题标题】:Why do I need to use finally to close resources?为什么我需要使用 finally 来关闭资源?
【发布时间】:2011-10-04 17:56:42
【问题描述】:

大多数时候,我看到 finally 块的唯一用途是

FileInputStream f;
try{
    f= new FileInputStream("sample.txt");
    //something that uses f and sometimes throws an exception
}
catch(IOException ex){
    /* Handle it somehow */
}
finally{
    f.close();
}

我的问题是,如果 f 的作用域以封闭块结束,为什么我们需要在 finally 中关闭它?

【问题讨论】:

  • 在您的情况下,f 的范围不会以 try-block 结束
  • @Oli Charlesworth:这显然是一个可读的例子。
  • 创建文件引用不会抛出异常(或创建文件句柄),以备将来参考。
  • FWIW,在 Java 7 中,您可以使用 try-with-resources 构造:download.oracle.com/javase/tutorial/essential/exceptions/…

标签: java try-catch finally


【解决方案1】:

因为垃圾回收与资源清理是一回事。

例如,如果您有一个超出范围的 JDBC 连接对象,则不会向数据库服务器发送任何信号来指示不再需要打开的游标和连接。如果没有这些消息,您最终会耗尽可用的游标和连接的数量。

与文件句柄和任何其他资源相同。自己打扫干净。

【讨论】:

  • 因为finally块中的代码保证执行,即使抛出异常。
  • @Joe 很好的例子。但是如果你有一个抛出异常的 catch 块,永远不要在 finally 块中返回一些东西。在那种情况下,你的异常将永远不会被抛出......我很难学会这一点;-)
【解决方案2】:

好吧,你举了一个不好的例子——我怀疑你的意思是 FileInputStream——但基本原因是 Java 没有确定性终结。

变量f 的范围以它声明的块结束(不是try 块),但这并不意味着一定没有对不再有对象 - 垃圾收集器既不会最终确定对象,也不会以任何确定性方式对其进行垃圾收集。

除非您希望让资源闲置任意时间(并延迟垃圾回收,因为终结器需要在最终释放内存之前进行额外一轮的回收),否则您应该明确关闭资源。

基本上Java支持RAII,就像C++一样;你不应该尝试像使用 C++ 一样使用它。

【讨论】:

  • 编辑以反映您的建议:我只是想出了一个可关闭的内存,所以感谢您给我一个实际适用的:P
【解决方案3】:

因为 finally 每次都会被调用,即使你遇到了异常。 finally 块确保您关闭文件/连接。

【讨论】:

    【解决方案4】:

    原因是 Java 不保证对象的特定引用一旦超出范围就会被垃圾回收。所以对于引用有限系统资源的对象,比如文件描述符,仅仅等待垃圾回收是不够的。

    但请注意,java.io.File 实际上并不是这样的对象。

    【讨论】:

      【解决方案5】:

      我们通过try catch finally处理异常,finally每次执行都会阻塞,但不能保证catch,因为catch阻塞只有在参数传入的异常匹配时才会执行。 例如,如果我们打开了任何数据库连接,所以必须在离开前关闭它,这必须在 finally 中实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-28
        • 1970-01-01
        • 1970-01-01
        • 2014-02-08
        • 2011-05-27
        • 1970-01-01
        • 2021-02-06
        • 2013-11-20
        相关资源
        最近更新 更多