有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何关闭Java流?

每当我看到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将不会被分配,而且无论如何也没有什么可关闭的,不是吗


共 (2) 个答案

  1. # 1 楼答案

    每次检索具有以下结构的InputStream时

    InputStream stream = connection.openConnection();
    

    有三种可能的结果:要么该方法返回正确的InputStream,要么返回null,要么抛出异常

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

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

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

    2)该方法返回null

    在这种情况下,您还应该在try块中进行null检查。如果是这样,try块通常不执行任何操作,finally块也必须进行null检查。否则,您的最后一个区块将抛出NPE

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

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

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

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

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

    现在是Java7及其try-with-resources结构。这确实是一个更好的机制,因为它有一个隐式finally块,其中流是闭合的。如果try块中存在异常,并且隐式finally块也抛出异常,那么第一个异常(从try块内部)将传递给调用方。那更合适。而且语法更易于阅读

  2. # 2 楼答案

    我同意你的看法

    带有null赋值的额外步骤是不必要的,也是丑陋的。您甚至可以将stream设为final

    我唯一会这样写的是,如果您有多个需要清理的资源(JDBC经常使用),并且您希望避免多个嵌套的try/finally块(但通常我还是会使用这些块)

    对于Java7,您可以使用try-with构造