2013-07-12 27 views
0

每当我看到Java 6的流处理,它的完成几乎是这样的:如何关闭Java流?

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

它会抛出一个异常,如果connection.openConnection()失败..你的尝试,最后没有任何意义,并假设不失败,并为空'流'然后在最后会抛出'NullPointerException' – nachokk

+0

是的,但如果当前与可能触发IOException的流进行交互,点所隐藏的是什么。 – Taig

+0

@nachokk但该方法已经抛出异常。另外,可能任何使用'stream'的操作都会抛出一个'Exception'。 –

回答

4

我同意你的意见。

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

我只会写这样的东西,如果你有多个资源需要清理(发生在JDBC上),并且你想避免多个嵌套try/finally块(但通常是I去那些无论如何)。

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

+0

我下面的评论我根本不同意,这样你就可以失去异常......考虑到某些错误发生了业务异常,那么流为空...然后stream.close()会抛出NullPointerException,并且你失去了业务异常..使最终的流解决这个例子,但.. – nachokk

+0

Stream.close()'永远不会被调用,因为该方法不会在IOException之后终止被扔在第一行。 – Taig

+0

如果业务异常抛出并且'stream'为null,那么您不会指定'try block'中发生了什么,那么您将失去异常。 – nachokk

0

每当你与构建检索的InputStream像

InputStream stream = connection.openConnection(); 

有三种可能的结果:要么该方法返回一个适当的InputStream,或返回null,或者它抛出一个异常。

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

1)方法返回一个适当的输入流。

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

2)该方法返回null。

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

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

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

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

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

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

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

+0

2)Java doc中没有暗示'URL.openConnection()'可能返回'null'。如果它确实会导致失败,那是真的。 3)请注意,'URL.openConnection()'不是从'try'块中调用的。所以最后不会执行。该方法的执行将停在第一行并转发一个'IOException'。 – Taig

+0

是的,你是对的。这两个代码片段在技术上都是等同的。事实上,我总是使用静态工具方法来“静静地”关闭一个只使用了一行代码的流。这是比较常见的,但随着Java 7的try-with-resources声明已经过时。 – Seelenvirtuose