每当我看到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
将不会被分配,然后无论如何也无法关闭,不是吗?
答案 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块内部)将被传递给调用者。这非常适合。阅读语法要好得多。