简体   繁体   English

当我有一个黑盒子转换为/从字节数组转换时,如何在Java中序列化和反序列化?

[英]How do I serialize and deserialize in Java when I have a black box to convert to/from a byte array?

I have a class that is something like the following: 我有一个类如下的类:

public class Foo {
  static byte[] convertToArray(Foo f);
  static Foo convertToFoo(byte[] ba);
}

How can I use convertToArray and convertToFoo to allow Foo to implement java.io.Serializable? 如何使用convertToArray和convertToFoo来允许Foo实现java.io.Serializable? The default serialization procedure doesn't seem like a good solution for my class because it would require changing a lot of other classes to implement Serializable. 默认的序列化过程对我的类来说似乎不是一个好的解决方案,因为它需要更改很多其他类来实现Serializable。 However, I already have a way to go to and from bytes, so there should be an easy way for Foo to implement serializable without having to declare all dependent members as Serializable. 但是,我已经有了一种去往字节的方法,因此Foo应该有一种简单的方法来实现serializable,而不必将所有依赖成员声明为Serializable。 I suspect overriding readObject and writeObject is the way to go, but what is the correct way to do this, since these are instance methods with return type void? 我怀疑覆盖readObject和writeObject是要走的路,但是这样做的正确方法是什么,因为这些是返回类型为void的实例方法?

Check out Externalizable , which is a subinterface of Serializable. 查看Externalizable ,它是Serializable的子接口。 Its readExternal and writeExternal methods delegate the serialization details to the programmer, which sounds appropriate in your case. 它的readExternalwriteExternal方法将序列化细节委托给程序员,这在你的情况下听起来很合适。

During deserialization (in your implementation of readExternal ), you will need to use Foo.convertToFoo to convert the bytes from an ObjectInput to a Foo object, and then copy all of the state of that Foo object into this . 在反序列化期间(在readExternal的实现中),您将需要使用Foo.convertToFoo将字节从ObjectInput转换为Foo对象,然后将该Foo对象的所有状态复制this对象中。

A snippet from the Javadoc that describes the semantics of Externalizable: 来自Javadoc的片段,描述了Externalizable的语义:

Only the identity of the class of an Externalizable instance is written in the serialization stream and it is the responsibility of the class to save and restore the contents of its instances. 只有Externalizable实例的类的标识才会写入序列化流中,类的责任是保存和恢复其实例的内容。 The writeExternal and readExternal methods of the Externalizable interface are implemented by a class to give the class complete control over the format and contents of the stream for an object and its supertypes. Externalizable接口的writeExternal和readExternal方法由类实现,以使类完全控制对象及其超类型的流的格式和内容。 These methods must explicitly coordinate with the supertype to save its state. 这些方法必须明确地与超类型协调以保存其状态。 These methods supersede customized implementations of writeObject and readObject methods. 这些方法取代了writeObject和readObject方法的自定义实现。

Assuming your class is final then you probably want to use a serial proxy (see Effective Java). 假设您的类是final那么您可能希望使用串行代理(请参阅Effective Java)。 Implement Serializable , but make readObject , readObjectNoData and writeObject throw an exception. 实现Serializable ,但使readObjectreadObjectNoDatawriteObject抛出异常。 Use writeReplace to produce a serialisable proxy object containing the binary data. 使用writeReplace生成包含二进制数据的可序列化代理对象。 In the proxy, use readResolve to create a Foo from the data. 在代理中,使用readResolve从数据创建Foo

public final class Foo implements Serializable {
    private static final long serialVersionUID = 42L;
    private static final ObjectStreamField[] serialPersistentFields = { }
    static byte[] convertToArray(Foo f) { ... }
    static Foo convertToFoo(byte[] ba) { ... }

    private void writeObject(
        ObjectOutputStream out {
    ) throws IOException {
        throw new NotSerializableException();
    }
    private void readObject(
        ObjectInputStream in
    ) throws IOException, ClassNotFoundException {
        throw new NotSerializableException();
    }
    private void readObjectNoData( 
    ) throws ObjectStreamException {
        throw new NotSerializableException();
    }
    private Object writeReplace() throws ObjectStreamException {
        return new FooSerialProxy(this);
    }
}

/* pp */ final class FooSerialProxy implements Serializable {
    private static final long serialVersionUID = 42L;
    private final byte[] data;
    /* pp */ FooSerialProxy(Foo foo) {
        this.data = Foo.convertToArray(foo);
    }
    private Object readResolve() throws ObjectStreamException {
        return Foo.convertToFoo(data);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM