如何关闭Java Stream?

时间:2013-07-12 02:12:52

标签: java stream try-catch

每当我看到Java 6 Stream处理时,它的完成就像这样:

public void myMethod() throws Exception
{
    InputStream stream = null;

    try
    {
        stream = connection.openConnection();
        ...
    }
    finally
    {
        if( stream != null )
        {
            stream.close();
        }
    }
}

但我不明白为什么这是必要的。这不会以同样的方式工作吗?

public void myMethod() throws Exception
{
    InputStream stream = connection.openConnection();

    try
    {
        ...
    }
    finally
    {
        stream.close();
    }
}

如果openConnection()失败,则stream将不会被分配,然后无论如何也无法关闭,不是吗?

2 个答案:

答案 0 :(得分:4)

我同意你的看法。

null分配的额外步骤是不必要和丑陋的。你甚至可以让stream最终。

我唯一一次写这样的东西就是你有多个需要清理的资源(很多用JDBC),你想要避免多个嵌套的try / finally块(但通常我会去无论如何)。

使用Java 7,您可以使用try-with构造。

答案 1 :(得分:0)

每次使用类似

的构造检索InputStream时
InputStream stream = connection.openConnection();

有三种可能的结果:方法返回正确的InputStream,或者返回null,否则会抛出异常。

让我们看看所有三种可能性:

1)该方法返回了正确的输入流。

在这种情况下,try块只是继续,如果它没有遇到任何其他问题(也就是例外),它通常在执行finally块之后结束。

2)该方法返回null。

在这种情况下,您还应该在try块中进行空检查。如果是这样,你的try块通常什么都不做,finally块也必须进行空检查。否则你的finally块会抛出一个NPE。

如果你没有防止null返回,try块内的代码将抛出NPE(我假设在那里使用了流变量)。在这种情况下,如果没有空检查,则将执行finally块并再次抛出NPE。在后一种情况下,只有finally块中的第二个NPE实际上被抛给调用者。

3)检索输入流的方法调用会引发异常。

在这种情况下,try块将结束,这会立即导致finally块执行,然后该方法将突然结束。但是哪个例外呢?这取决于。

考虑抛出的异常是一个IOException,在大多数情况下会被抛出。首先,变量仍将具有空引用!如果没有空检查,则finally块将再次抛出NPE。在这种情况下,第一个异常(IOE)将被遗忘,因为只有NPE会被传递给您的方法的调用。这不是一个好主意。

总而言之,空检查确实是必要的。

Java 7带有try-with-resources构造。这确实是一个更好的机制,因为它有一个隐含的finally块,其中流是关闭的。如果try块中存在异常,并且隐式finally块也抛出异常,则第一个异常(从try块内部)将被传递给调用者。这非常适合。阅读语法要好得多。