从公共方法返回InputStream

13

我有一个类,在某些情况下,从公共方法返回InputStream似乎是正确的。

public class MyClass {

    private File _file;

    ...

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

然而,我对这样做也非常谨慎,因为它将关闭这个流的责任放在了调用者身上。有哪些方式可以避免这个问题?


我认为这不是一个问题。Java API中已经完成了(例如,ServletResponse.getOutputStream())。 - Harry Cutts
1
虽然我喜欢尝试制作一个减少错误可能性的API,但你可以期望使用它的人有一定的最低要求。我认为关闭“InputStream”就是其中之一 - 如果他们不记得这样做,那么他们只能怪自己。 - Vala
4个回答

10

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

但是,如果返回InputStream“感觉正确”,难道调用者不应该期望一个InputStream及其相关内容,包括完成后需要关闭流吗?


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()引发异常。


2
实际上,如果不了解该类的更多细节,则无法做太多事情。您可以通过MyClass中的方法提供文件处理(需要了解文件内容的含义),并在流为空时关闭该流。但是除此之外,该类的用户负责该对象,你无法避免这点。由于没有像C++中的析构函数那样的能力,因此您无法100%地对离开类范围的任何对象负责。

您可以在您的类中放置一个close()方法,以清除任何打开的文件处理程序、连接等,并要求该类的用户负责调用close()。请参见此问题以了解如何使用finalize方法来跟踪调用者是否正确关闭您的类。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接