AutoCloseable contract:写入close()允许的资源?

时间:2018-02-08 12:26:00

标签: java

我偶然发现了内部的以下构造:

class OurXmlWriter implements AutoCloseable {
    private XMLStreamWriter streamWriter;
    public OurXmlWriter(OutputStream stream) {
        streamWriter = XMLOutputFactory.newInstance()
                        .createXMLStreamWriter(outputStream, "UTF-8");
    }

    @Override
    public void close() {
        try {
            // is this allowed?
            streamWriter.writeEndDocument();
        } catch (XMLStreamException e) {
            throw new RuntimeException();
        } finally {
            try {
                streamWriter.close();
            } catch (XMLStreamException e) {
                throw new RuntimeException();
            }
            streamWriter = null;
        }
    }
}

我们遇到的问题是:

try (OurXmlWriter writer = new OurXmlWriter(new FileOutputStream("output.xml"))) {
    writer.writeStartTag();
    // write some data elements correctly
    throw new OutOfMemoryError(); // that's not done explicitly but happens
}

这仍然会调用close() - 这样就可以了,但会导致xml正确关闭(虽然不可靠,因为我确信它不能保证在{{1}之后成功})。

所以问题基本上是XML是有效的,尽管我们不喜欢它(因此在错过错误的情况下不会意外地处理输出)。我正在思考如何最好地处理这种情况 - 从Error删除结束标记 - 这需要大量的分析重新测试 - 或者只是不使用try-with-resource来控制是否它被称为。

但我的一般问题是: 当您被close()告知时,AutoCloseable合同是否允许仍然写入您的资源?我一直在阅读javadoc,但它并没有真正明确禁止它。我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

基本上Javadoc中没有任何内容表明它不会被允许,事实上它说

  

请注意,与此close的{​​{1}}方法不同   java.io.Closeable方法要求是幂等的。换一种说法,   不止一次调用此close方法可能会有一些可见的方面   效果,与要求无效的close不同   如果不止一次被召唤。

允许副作用,甚至不要求该方法是幂等的。考虑到写文档的结尾是一个相对不令人惊讶的副作用,我会说没关系。但当然只是因为它不被禁止并不意味着它是允许的,YMMV,基于意见,咨询你的内部规则手册等。

答案 1 :(得分:1)

Java Standard类库中有一些示例,close()方法必须执行写操作。其中一个例子是DeflaterOutputStream,其javadoc声明:

  

将剩余的压缩数据写入输出流并关闭基础流。

关键是压缩流的最后一位只能在您知道流被关闭时才会出现。冲洗是不够的。

因此将此与@Kayaman结合使用,并且有明确证据表明允许流在close()期间执行写入。

(另一个示例是BufferedOutputStream,其中close()在需要的情况下相当于flush()来电。)