11

我有一个类,一方面,InputStream从公共方法返回一个感觉是正确的,例如

public class MyClass {

    private File _file;

    ...

    public InputStream getInputStream() {
        return new FileInputStream( _file );
    }
}

但是,我对此也非常谨慎,因为它使调用者有责任关闭此流。我可以通过哪些方式潜在地避免这个问题?

4

4 回答 4

9

取决于为什么这是您眼中的问题。如果您绝对必须返回一个InputStream并且有问题的文件不是太大,您可以将整个文件缓冲到一个字节数组中,关闭原始流和return new ByteArrayInputStream(buf). 关闭 aByteArrayInputStream不是必需的(实际上没有效果)。

但是,如果返回 an “感觉正确” InputStream,那么调用者应该期待anInputStream以及随之而来的所有事情,包括完成后关闭流的必要性,这难道没有意义吗?

于 2012-11-16T16:40:16.767 回答
4

回归InputStream本质上并不是一件坏事。现在,如果您希望您的调用者在不负责关闭资源的情况下访问数据,您可以这样做:

interface InputReader {
    void readInput(InputStream is);
}
public class MyClass {
    void feed(InputReader ir){
       try(InputStream is=new FileInputStream( _file )){
          ir.readInput(is);
       }
    }
}

调用者指定一个实例InputReader,它将接收可关闭资源作为参数,并且不再负责关闭它。

MyClass myClass = ... ; //Get the instance
myClass.feed( new InputReader() {
    @Override
    void readInput(InputStream is){
       ... ; // Use at will without closing
    }
});

应该考虑InputStream在将其传递给抛出和异常之前对其InputReader进行.close()装饰。

于 2012-11-17T08:43:12.080 回答
2

实际上,如果不了解有关课程的更多详细信息,您将无能为力。您可以通过 MyClass 中的方法提供文件处理(这需要知道文件内容的含义)并在流为空时关闭流。但除此之外,该类的用户对该对象负责,您无法真正避免这种情况。如果没有析构函数的能力,就像在 C++ 中一样,你不能对任何离开你的类范围的对象负 100% 的责任。

可以做的是close()在您的类上放置一个方法来清理所有打开的文件处理程序、连接等,并要求该类的用户负责调用close(). 有关如何使用该方法跟踪调用者是否正确关闭您的课程的一些讨论,请参阅此问题。finalize

于 2012-11-16T16:39:03.100 回答
1

...因为它使调用者有责任关闭此流。

是的,调用者负责处理返回的流的关闭操作。由于您的方法无法跟踪其返回的内容,因此该任务完全属于调用者。这种情况和使用异常有一个类比。开发人员使用异常是因为 API 作者不能总是控制他们呈现给我们的内容。我们必须小心,例如当有可能将数字除以零时。

于 2012-11-16T16:37:42.390 回答