Java 我赢了';不要在finally-blcok中使用try-catch语句。(爪哇)

Java 我赢了';不要在finally-blcok中使用try-catch语句。(爪哇),java,stream,garbage-collection,connection,try-catch-finally,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 except

下面是一些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;
    }
但我看到“流对象未被垃圾收集”

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

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

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

但最终,您还是会在finally块中使用try/catch

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

如果你使用番石榴,你也可以使用,这和上面的代码差不多。你也可以看看,这很有趣

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


如果未关闭并设置为NULL,您可能会留下一个僵尸连接。

让其他人来尝试捕获并使用

closequiety()
-方法之一(例如)应该正是您所需要的:

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


从Java7开始,假设是这样的

try (Connection conn = DriverManager.getConnection(props)) {
    ...
}
Java 7之前

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

如果为空且未关闭,请确保所有方法始终获得新的打开连接。


您需要知道的唯一一件事是,任何时候获得连接时,都必须将其关闭(因此出现finally块),否则您可能会在应用程序中打开该连接,并最终耗尽可用的连接。

另一个解决方法是删除方法中的所有捕获:

public void someWork() throws SQLException{
    Connection c;
    try {
        // do something
    } finally {
        if (conn != null){
            c.close();
        }
    }
}
然后在调用
someWork
方法的主方法中的方法之外执行错误检查,或者将其包装到另一个方法中,在该方法中调用
someWork()


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

您可能不喜欢该代码,但在这种情况下它是必要的。(尽管可以用@fge的
closequity
method这样的方法包装代码。)

但还有一个更基本的问题。
块中更改
某些工作
以关闭连接不足以防止泄漏。。。在这种情况下

为什么?

考虑这一点:

SomeClass sc = new SomeClass(createConnection());
// do some stuff
sc.someWork();
Q1:如果在“Dosomething”代码中抛出异常,会发生什么

问题2:如果在创建/构造
SomeClass
时引发异常,会发生什么情况?(注意:即使使用最简单的构造函数,这也是可能的。例如,
new
操作可能会抛出OOME…)

答:连接对象已泄漏。。。在两个基地


修复方法是在try/catch/finally内或之前分配资源(例如连接对象);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
}
前提是
连接
实现了
自动关闭
接口。Java 7版本是一个更复杂的实现的“语法糖”,它负责检查
null
,调用
close()
,并智能地处理任何产生的异常。(JLS提供了“使用资源进行尝试”实际操作的详细信息。)


记录在案:

  • 问题不在于垃圾收集。问题是需要关闭
    连接
    对象

  • 分配
    null
    不会导致关闭对象。它甚至不会导致垃圾收集。充其量,它可以使对象符合垃圾收集的条件。。。在将来的一些GC运行中

  • 捕获异常是一个非常糟糕的主意。请阅读以下内容:


你为什么不呢?说真的,我看不出有什么理由任意禁止嵌套在另一个内部的语言构造。更重要的是,为什么要忽略这个异常?每次我看到一个try-catch块吞下了一个异常,我都想哭。这只是在以后调试时让某人的生活变得困难。谢谢你提供的信息。我应该写我的环境。我使用JDK6。但我真的找不到任何理由为每种情况捕获异常。我通常使用
Exception e
e.printStackTrace()
然后它的工作原理是这样的
java.sql.SQLException:ORA-00936:oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:138)
你真的认为这是一种不好的方式吗?我想我捕捉到了错误是什么,它在哪里。我要说的是,如果捕捉到
异常
,也会捕捉到与您的应用程序无关的异常workflow@user2503993-那是不幸的。但是如果你打算使用一种过时的语言,你必须忍受它的局限性。学习“喜欢它”。@user2503993-还要注意(并告诉你的老板/客户)Java6已经下线了。没有更多的安全更新。。。除非他/他们签订Oracle Java支持合同。
SomeClass sc = new SomeClass(createConnection());
// do some stuff
sc.someWork();
Connection c = createConnection();
try {
    // do something
} catch (SomeException e) {
    // some exception code
} finally {
    if (c != null){
        try {c.close();} catch (SomeException e) {}
    }
}
try (Connection c = createConnection()) {
    // do something
} catch (SomeException e) {
    // some exception code
}