java AutoCloseable协定:close()中允许写入资源?
我偶然发现了以下内部构造:
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(尽管不可靠,因为我确信它不一定在Error
之后成功)
因此,问题基本上是XML是有效的,尽管我们不希望它是有效的(因此,在丢失错误的情况下,不会意外地进一步处理输出)。我正在考虑如何最好地处理这种情况—从close()
中删除结束标记写入—这将需要大量的分析重新测试—或者只是不使用try with resource来控制是否调用它
但我的一般问题是:
当您被告知close()
时,AutoCloseable
契约是否允许仍然写入您的资源?我一直在阅读javadoc,但它并没有明确地禁止它。我错过什么了吗
# 1 楼答案
基本上,Javadoc中没有任何东西表明它是不被允许的,事实上它是这么说的
它允许副作用,甚至不要求方法是幂等的。考虑到写文档结尾是一个相对不令人惊讶的副作用,我认为这没关系。但当然,仅仅因为它没有被禁止并不意味着它是被允许的,YMMV,基于意见,查阅你的内部规则手册等等
# 2 楼答案
Java标准类库中有一些示例,其中
close()
方法必须执行写入操作。一个这样的例子是DeflaterOutputStream
,其javadoc声明:关键是,压缩流的最后一位只能在您知道该流正在关闭时才可用。冲洗不够
因此,将其与@Kayaman结合起来,就有明显的证据表明允许流在
close()
期间执行写入(另一个例子是
BufferedOutputStream
,其中close()
执行与flush()
调用等价的操作(如果需要的话)