每当我看到Java 6流处理时,它都是这样做的:
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
将不会被分配,并且无论如何都没有什么可关闭的,不是吗?
null
赋值的额外步骤是不必要的,而且很难看。你甚至可以让stream
成为决赛。
我唯一会写这样的东西的时候是,如果您有多个资源需要清理(JDBC经常发生这种情况),并且您希望避免多个嵌套的try/finaly块(但通常我都会选择这些块)。
使用Java7,您可以使用try-with-构造。
每次使用类似的构造检索InputStream时
InputStream stream = connection.openConnection();
有三种可能的结果:要么该方法返回正确的InputStream
,要么返回null
,要么抛出异常。
让我们看看所有三种可能性:
1) 该方法返回了正确的输入流。
在这种情况下,try块只是继续,如果它没有遇到任何其他问题(也称为异常),它通常在执行finally块后结束。
2) 该方法返回null。
在这种情况下,您还应该在try块中进行null检查。如果是这样的话,try块通常什么都不做,finally块也必须进行null检查。否则,你的最后一个盖帽会抛出一个NPE。
如果不防止返回null,try块中的代码将抛出NPE(我假设流变量在那里使用)。在这种情况下,finally块将被执行,并将再次抛出一个NPE,如果它没有进行null检查的话。在后一种情况下,实际上只有来自finally块的第二个NPE被抛出给调用者。
3) 用于检索输入流的方法调用引发异常。
在这种情况下,try块将结束,这将立即导致finally块执行,然后方法将突然结束。但有哪个例外?这取决于情况。
考虑抛出的异常是IOException,在大多数情况下都会抛出它。首先,变量仍将具有null引用!如果finally块没有空检查,那么它将再次抛出一个NPE。在这种情况下,第一个异常(IOE)将被忘记,因为只有NPE会被传递给方法的调用。这不是个好主意。
总而言之,空检查确实是必要的。
现在,Java 7推出了它的try with resources构造。这确实是一个更好的机制,因为它有一个隐式的finally块,在那里流是关闭的。如果try块中存在异常,并且隐式finally块也抛出异常,则tnow第一个异常(来自try块内部)将传递给调用者。这更合适。而且语法读起来更好。