1

在处理流时,我经常在 Java 文档和其他人的代码中看到以下模式:

FileInputStream fis = null;
try {
  fis = new FileInputStream("some.file");
  // do something useful with fis
} finally {
  if (fis != null) {
    fis.close();
  }
}

但是我个人更喜欢不同的模式:

FileInputStream fis = new FileInputStream("some.file");
try {
  // do something useful with fis
} finally {
  fis.close();
}

我喜欢后者的简洁,我认为这是正确的。但我对正确性的看法是对的吗?是否有客观的理由偏爱一个而不是另一个?

更新

即使我编写的示例几乎是如何在现实生活中编写这样的代码,我的模式仍然更加简洁。比较文档方法:

public Object processFile(String fn) throws MyException {
  FileInputStream fis = null;
  try {
    fis = new FileInputStream(fn);
    return new Object(); // somehow derived from fis
  } catch (FileNotFoundException e) {
    throw new MySubExceptionForNotFound(e);
  } catch (IOException e) {
    throw new MySubExceptionForIoError(e);
  } finally {
    if (fis != null) {
      IOUtils.closeQuietly(fis);
    }
  }
}

用我的方法:

public Object processFile(String fn) throws MyException {
  try {
    FileInputStream fis = new FileInputStream(fn);
    try {
      return new Object(); // somehow derived from fis
    } finally {
      IOUtils.closeQuietly(fis);
    }
  } catch (FileNotFoundException e) {
    throw new MySubExceptionForNotFound(e);
  } catch (IOException e) {
    throw new MySubExceptionForIoError(e);
  }
}

我的短了一行!:D

fis.close()有趣的是,如果您决定使用而不是IOUtils.closeQuietly()“官方”代码将再增长 4 行,我的代码不会改变。

4

3 回答 3

1

使用try-with-resources

try (FileInputStream fis = new FileInputStream("some.file")) {
    // some code here
}

要回答为什么推荐模式是这样的问题,请考虑new FileInputStream(String)引发您可能应该捕获的检查异常的事实;这

FileInputStream fis = null;
try {
    fis = new FileInputStream("somefile.txt");
} catch (FileNotFoundException e) {
    return false;
} finally {
    if (fis != null) {
        fis.close();
    }
}

允许您在与其他文件相关异常相同的 try/catch 块中处理它。与以下内容相比,这具有简洁和减少嵌套的优势:

try {
    FileInputStream fis = new FileInputStream("some.file");
    try {
        // do something useful with fis
    } finally {
        fis.close();
    }
} catch (FileNotFoundException e) {
    return false;
}

如果你没有捕捉到异常而只是让它传播,那么你的建议就更清晰了——但是考虑到 IO 库中大量使用检查的异常(包括来自类构造函数),捕捉和处理异常是很常见的,并且我认为只有一种模式用于教程目的而不是每次都向某人展示略有不同的模式是有意义的。

于 2014-08-13T22:44:22.140 回答
1

您发布的第二个示例不会尝试/捕获... = new FileInputStream("...");如果加载文件失败将返回的可能错误。在第一个示例中,虽然您也自动捕获了FileInputStream给出的错误。

我个人会选择第一个以获得更好的错误处理。

于 2014-08-13T22:39:03.943 回答
1

除非您从方法中抛出异常,否则第二个示例不会编译,因为FileNotFoundException它是一个已检查的异常。

Compile.java:5: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
        FileInputStream fis = new FileInputStream("some.file");

第一个示例也无法编译,因为您缺少相应的catch块。这是一个编译示例。

import java.io.*;
public class Compile {

    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("some.file");
            // do something useful with fis

            if (fis != null) {
                fis.close();
            }
        }
        catch (FileNotFoundException fnf) {
        }
        catch (IOException ioe) {
        }
        finally {
        }
    }
}
于 2014-08-13T22:40:53.373 回答