有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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,但它并没有明确地禁止它。我错过什么了吗


共 (2) 个答案

  1. # 1 楼答案

    基本上,Javadoc中没有任何东西表明它是不被允许的,事实上它是这么说的

    Note that unlike the close method of java.io.Closeable this close method is not required to be idempotent. In other words, calling this close method more than once may have some visible side effect, unlike Closeable.close which is required to have no effect if called more than once.

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

  2. # 2 楼答案

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

    Writes remaining compressed data to the output stream and closes the underlying stream.

    关键是,压缩流的最后一位只能在您知道该流正在关闭时才可用。冲洗不够

    因此,将其与@Kayaman结合起来,就有明显的证据表明允许流在close()期间执行写入

    (另一个例子是BufferedOutputStream,其中close()执行与flush()调用等价的操作(如果需要的话)