我偶然发现了内部的以下构造:
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,但它并没有真正明确禁止它。我错过了什么吗?
答案 0 :(得分:2)
基本上Javadoc中没有任何内容表明它不会被允许,事实上它说
请注意,与此
close
的{{1}}方法不同java.io.Closeable
方法不要求是幂等的。换一种说法, 不止一次调用此close
方法可能会有一些可见的方面 效果,与要求无效的close
不同 如果不止一次被召唤。
允许副作用,甚至不要求该方法是幂等的。考虑到写文档的结尾是一个相对不令人惊讶的副作用,我会说没关系。但当然只是因为它不被禁止并不意味着它是允许的,YMMV,基于意见,咨询你的内部规则手册等。
答案 1 :(得分:1)
Java Standard类库中有一些示例,close()
方法必须执行写操作。其中一个例子是DeflaterOutputStream
,其javadoc声明:
将剩余的压缩数据写入输出流并关闭基础流。
关键是压缩流的最后一位只能在您知道流被关闭时才会出现。冲洗是不够的。
因此将此与@Kayaman结合使用,并且有明确证据表明允许流在close()
期间执行写入。
(另一个示例是BufferedOutputStream
,其中close()
在需要的情况下相当于flush()
来电。)