我不会在finally块中使用try-catch语句。 (Java)的

时间:2013-06-20 09:18:36

标签: java stream garbage-collection connection try-catch-finally

这是一些java代码。

public class SomeClass {
private Connection connection;

public SomeClass(Connection c) {
    connection = c;
}
public void someWork(){
    Connection c;
    try {
        // do something
    } catch (Exception e) {
        // some exception code
    } finally {
        if (conn != null){
            try {c.close();} catch (Exception e) {}
        }
    }
}

}

但我不喜欢代码

if (conn != null){
        try {c.close();} catch (Exception e) {}
    }

所以我认为代码

...catch (Exception e) {
        // some exception code
    } finally {
        c = null;
    }

但我看到'Stream object not Garbage Collected。'

我不会在finally块中使用try-catch语句。 请给我另一种方式。

7 个答案:

答案 0 :(得分:6)

只需创建一个静态实用程序方法:

private static void closeQuietly(final Connection conn)
{
    if (conn == null)
        return;
    try {
        conn.close();
    } catch (WhateverException ignored) {
    }
}

然后

conn = whatever(); // create it there, not in the try block
try {
    // work
} catch (WhateverException e) {
    // whatever
} finally {
    closeQuietly(conn);
}

但最终,你在finally块中使用try / catch。

请注意,抓住Exception糟糕的主意。捕获由conn.close()专门提出的异常。捕获Exception意味着您还可以捕获所有RuntimeException个;这是一件坏事(tm)。

如果你使用Guava,你也可以使用Closeables.closeQuietly(),它与上面的代码完全相同。您也可以查看Closer,这非常有趣。

最后(双关语):如果使用Java 7,请改用try-with-resources语句(参见AutoCloseable):

try (
    conn = whatever();
) {
    // ...
}

答案 1 :(得分:1)

解决此问题的另一个方法是在方法中删除所有内容:

public void someWork() throws SQLException{
    Connection c;
    try {
        // do something
    } finally {
        if (conn != null){
            c.close();
        }
    }
}

然后,您在调用someWork方法的main方法中的方法外部进行错误检查,或者将其包装在另一个调用someWork()的方法中:

 public void callSomeWork(){
    try{
     someWork();
    }catch(SQLException ex){
    //handle SQL error here
    }
 }

这样在try或finally中抛出的错误将在一个SQLException中声明。

答案 2 :(得分:1)

您可能不喜欢该代码,但在这种情况下,这是必要的。 (虽然你可以用@ fge' s closeQuietly方法包装代码。)

但是存在一个更基本的问题。更改someWork以关闭finally块中的连接不足以以防止泄漏......在这种情况下!!

为什么?

考虑一下:

SomeClass sc = new SomeClass(createConnection());
// do some stuff
sc.someWork();

Q1:如果在"中做了一些异常,会发生什么事情"码?

Q2:如果在创建/构建SomeClass时抛出异常会怎样? (注意:即使使用最简单的构造函数也可以这样做。例如,new操作可能会引发OOME ...)

答案:Connection对象在两个基地都泄露了!


修复是在try / catch / finally之前或之前分配资源(例如Connection对象); e.g。

Connection c = createConnection();
try {
    // do something
} catch (SomeException e) {
    // some exception code
} finally {
    if (c != null){
        try {c.close();} catch (SomeException e) {}
    }
}

在Java 7中,您也可以这样写:

try (Connection c = createConnection()) {
    // do something
} catch (SomeException e) {
    // some exception code
}

前提是Connection实现了AutoCloseable接口。 Java 7版本是"语法糖"对于更复杂的实现,它负责检查null,调用close()并智能地处理任何结果异常。 (JLS详细介绍了什么"尝试使用资源"实际上是。)


记录:

答案 3 :(得分:0)

如果未关闭,您可能会离开僵尸连接并设置为NULL。

答案 4 :(得分:0)

让别人做try-catch-stuff并使用Apache Commons IOUtils

其中一个closeQuietly()方法(例如this one)应该就是您所需要的:

  

等效于InputStream.close(),但将忽略任何异常。这个   通常用在finally块中。

答案 5 :(得分:0)

从Java 7开始,它就是这个

try (Connection conn = DriverManager.getConnection(props)) {
    ...
}

之前的Java 7

Connection conn = DriverManager.getConnection();
try {
  ...
} finally {
    conn.close();
}

答案 6 :(得分:0)

如果您取消并且未关闭,请确保所有方法始终获得新的开放连接。

您唯一需要知道的是,只要您获得连接,必须关闭它(因此最终阻止),否则您可能会在您的应用程序中打开该连接并最终耗尽可用的连接。