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? 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. 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. 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?
Check out Externalizable, which is a subinterface of Serializable. Its readExternal
and writeExternal
methods delegate the serialization details to the programmer, which sounds appropriate in your case.
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
.
A snippet from the Javadoc that describes the semantics of 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. 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. These methods must explicitly coordinate with the supertype to save its state. These methods supersede customized implementations of writeObject and readObject methods.
Assuming your class is final
then you probably want to use a serial proxy (see Effective Java). Implement Serializable
, but make readObject
, readObjectNoData
and writeObject
throw an exception. Use writeReplace
to produce a serialisable proxy object containing the binary data. In the proxy, use readResolve
to create a Foo
from the data.
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);
}
}
精彩评论