序列化中readObject / writeObject的使用
我正在阅读本文以了解有关Java序列化过程的更多信息。 说到readObject/writeObject
使用,我可以看到两个用例:
- 我们可以使用
writeObject
在序列化之前加密字节码。 从安全的角度来看,这是件好事。 - 我们可以使用
readObject
来执行需要在反序列化后立即执行的任何特定代码片段,当然从#1开始,我们甚至可以使用readObject
来解密序列化对象时被截取的字节代码。
在编写自定义readObject / writeObject方法时序列化/反序列化对象时是否还有其他实际情况? 或者,如果你能指出我可以看到readObject / writeObject的一些体面和实际用途的任何地方?
当您需要在反序列化对象后初始化瞬态(非序列化)字段时,自定义readObject
方法也很有用。
顺便说一句,请查看Effective Java,第11章 (我不确定第2版中的章节/项目编号是什么。)。 这是一篇关于序列化的精彩读物。
出于性能原因或向后兼容性原因,或者因为要序列化的字段不是Serializable,您可以实现自己的readObject / writeObject。
有关readObject / writeObject的好例子,我会查看JDK附带的源代码。 或者我会尝试http://www.google.co.uk/search?q=readObject+writeObject+examples
使用自定义序列化可能有几个原因:
- 性能。
- 与外部系统连接。 (超越您的范围,甚至只是非Java系统。)
- 需要一种人类可读的格式。
- 支持旧版本的序列化类。
仅举几例,但我相信还有更多。
我可以通过使用基于CipherOutputsStream的ObjectOutputStream来更好地解密。
writeObject / readObject最重要的用途是,如果要在多个代码修订版上保持Serialization稳定。 您的内部表示(成员变量)可能会更改,但序列化必须保持稳定,因为您与之通信的旧系统(例如,通过从文件中读取旧数据)。
但我更喜欢Externalizable接口用于这些情况,因为它更容易使用(没有隐式调用和只有jvm知道的方法)。
public class Employee implements Serializable { private static final long serialVersionUID = 1L; private int empno; private String ename; private String job; // setter & getter @Override public String toString() { return "Employee [empno=" + empno + ", ename=" + ename + ", job=" + job + "]"; } private void writeObject(ObjectOutputStream out) throws IOException { // default serialization // out.defaultWriteObject(); // custom serialization out.writeInt(empno); out.writeUTF(ename); // out.writeUTF(job); //job will not serialize } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // default deSerialization // in.defaultReadObject(); // custom deSerialization empno = in.readInt(); ename = in.readUTF(); // this.job = in.readUTF(); } }