如何使用Guava的InputSupplier或OutputSupplier api?

jlc*_*hen 24 java io guava

我是guava库的新手,我对InputSupplier和OutputSupplier很困惑.根据javadoc,它们分别只是InputStream和OutputStream的工厂.但是,我没有看到这两个接口有什么用处,有没有人能告诉我为什么我应该使用这两个API除了更高的抽象?

Col*_*inD 31

The main benefit of both of these interfaces is that they allow library code to control the whole lifecycle of the actual input/output objects. Guava's utilities never close an InputStream or OutputStream that you pass in directly, because that might not be what you want to happen. Even if they did, you'd still need try/finally to deal with errors creating objects. The suppliers are a sort of lazy callback that allow the actual objects to be created, used and closed all in one go without you having to do a lot of ugly try/finally and error handling.

For an example, just look at the code it takes to copy one file to another (with the actual copying and stream closing code minimized using Guava utilities):

File in = ...
File out = ...
FileInputStream inStream = new FileInputStream(in);
boolean threw = true;
try {
  /*
   * Note how two try/finally blocks are needed here, in case creating 
   * outStream fails.
   */
  FileOutputStream outStream = new FileOutputStream(out);
  try {
    ByteStreams.copy(inStream, outStream);
    threw = false;
  } finally {
    Closeables.close(outStream, threw);
  }
} finally {
  Closeables.close(inStream, threw);
}
Run Code Online (Sandbox Code Playgroud)

Then look at the code if you use suppliers instead:

File in = ...
File out = ...
ByteStreams.copy(Files.newInputStreamSupplier(in), 
    Files.newOutputStreamSupplier(out));
Run Code Online (Sandbox Code Playgroud)

  • +1.我喜欢你如何使用"生命周期"概念来解释它.我没有想到Guava只有在控制整个生命周期时才关闭这些资源这一事实.有一个完美的感觉.谢谢. (2认同)
  • Java 7中的一些优点通过try-with-resources语法得到了缓解,但`cgcio`可能还需要完整的Java 7重新设计. (2认同)

Eti*_*veu 4

使用Guava的InputSupplier / OutputSupplier,您不必自己处理实例化FileInputStreams / FileOutputStreams时抛出的各种IOExceptions。当 Guava 调用 InputSupplier.getInput() / OutputSupplier.getOutput() 工厂方法时,它会自动为您处理这些异常。

通过将输入/输出构造封装在这些工厂接口中,您可以推迟它们的实例化,从而推迟您需要处理它们可能抛出的 IOException / FileNotFoundException 的时间。事实上,您推迟了太多时间,以至于 Guava 为您处理了它。

然后您可以替换

    FileInputStream inputStream = null;
    try {
        inputStream = new FileInputStream(file);
    } catch (FileNotFoundException ex) {
        throw new RuntimeException(ex);
    }

    doSomething(inputStream);
Run Code Online (Sandbox Code Playgroud)

    InputSupplier<FileInputStream> inputStreamSupplier = Files.newInputStreamSupplier(file);

    doSomething(inputStreamSupplier);
Run Code Online (Sandbox Code Playgroud)

编辑:另请参阅 ColinD 的答案,了解 Guava 在控制其整个生命周期时(即,当它使用 InputSupplier / OutputSupplier 来获取它们时)如何为您关闭这些输入/输出。