将OutputStream与多个ObjectOutputStreams一起使用?

时间:2017-01-01 16:05:57

标签: java serialization objectoutputstream

要从特定的序列化格式中抽象,我想要定义以下内容:

public interface TransportCodec {
  void write(OutputStream out, Object obj) throws IOException;      
  Object read(InputStream in) throws IOException;
}

默认实现只使用Java对象序列化:

public void write(OutputStream out, Object obj) throws IOException {
  ObjectOutputStream oout = new ObjectOutputStream(out);
  oout.writeObject(obj);
  oout.flush();
}

显然缺少oout.close(),但出于某种原因:我希望能够通过对write的独立调用将多个对象写入同一个流中。查看ObjectOutputStream(jdk 1.8)的源代码,oout.close()关闭基础流,但也清除属于ObjectOutputStream的数据结构。但是,由于我将oout保留在垃圾收集器中,因此我不会因为没有关闭流而产生问题。

除了未来JDK确实需要oout.close()的风险之外,还有两个问题:

  1. 当没有关闭上面的ObjectOutputStream时,我在当前的JDK中松了什么。
  2. 首先序列化为ByteArrayOutputStream,然后将字节复制到out,即可关闭oout。还有更好的选择吗?

1 个答案:

答案 0 :(得分:0)

分成两个接口,使实现类“拥有”底层流。

优点:

  • 基础存储不再仅限于OutputStream / InputStream

  • 通过使两个接口扩展Closeable,现在可以在try-with-resources块中使用它们。

  • 来电者只需携带一个参考(例如TransportEncoder),并且不再需要携带该流(例如OutputStream)。

接口

public interface TransportEncoder extends Closeable {
    void write(Object obj) throws IOException;
}
public interface TransportDecoder extends Closeable {
    Object read() throws IOException;
}

ObjectStream实现

public final class ObjectStreamEncoder implements TransportEncoder {
    private final ObjectOutputStream stream;
    public ObjectStreamEncoder(OutputStream out) throws IOException {
        this.stream = new ObjectOutputStream(out);
    }
    @Override
    public void write(Object obj) throws IOException {
        this.stream.writeObject(obj);
    }
    @Override
    public void close() throws IOException {
        this.stream.close();
    }
}
public final class ObjectStreamDecoder implements TransportDecoder {
    private final ObjectInputStream stream;
    public ObjectStreamDecoder(InputStream in) throws IOException {
        this.stream = new ObjectInputStream(in);
    }
    @Override
    public Object read() throws IOException {
        try {
            return this.stream.readObject();
        } catch (ClassNotFoundException e) {
            throw new NoClassDefFoundError(e.getMessage());
        }
    }
    @Override
    public void close() throws IOException {
        this.stream.close();
    }
}