java 序列化与反序化
一 .java 序列化的用途
1. 将数据持久化到文件中
2. 在网络上传输字节序列
两种功能的示意图如下 :
<!----><!----><!----> <!----> <!---->
二 . 实现对象序列化的条件
1. 只有实现了 Serializable( 默认的序列化方式 ) 或 Externalizable( 继承 Serializable 接口 , 自定义实现来控制序列化时的行为 ) 接口的类才能被序列化 .
2.. 利用 java.io.ObjectOutputStream 类的 writeObject(Object obj) 来实现对象序列化操作 , 并将字节序列写入到到目标输出流中 . 利用它的 readObject() 方法从源输入流中读取字节流 , 再将数据反序列化成一个对象并返回该对象 .
三 . 通过实现 Serializable 接口序列化 . 和反序列化
1. 如果类 A 实现了 Serializable 接口 , 则对类 A 的非 static, 非 transient 的实例变量进行序列化和反序列化
此方法不能控制序列化时的行为 . 以下两种方法则行 .
2. 如果类 A 既实现了 Serializable 接口 , 又定义了 writeObject(Object obj) 方法和 readObject() 方法 , 由调用这两个方法进行序列化和反序列化 .
3. 如果类 A 实现了 Externalizable 接口 , 由该类必须实现 writeExternal(ObjectOutput out) 方法和 readExtername() 方法 . 在这种情况下 , 将按照这两个方法进行对象的序列化和反序列化 .
四 . 对象序列化和对象反序列化的步骤
对象序列化步骤 :
1. 创建一个对象输出流
2. 通过对象输出流的 writeObject(Object obj) 方法写对象
如 :
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filePath));//filePath: 文件路径
out.writeObject(obj);//obj: 要写入文件的对象
对象反序列化步骤 :
1. 创建一个对象输入流
2. 通过对象输入流的 readObject(j) 方法读取对象 .( 读取对象时是按照对列方式进行的 , 既先进先出 )
如 :
ObjectInputStream in = new ObjectInputStream (new FileInputStream(filePath));
in.readObject();// 读取对象
五 . 对于实现了 Serializable 接口反序列化过程
1. 如果内存中的对象所属的类还没有加载 , 则先加载并初始化这个类 , 如果在 classpath 中找不到这个类 , 则抛出 ClassNotFoundException
2. 在反序列化时 , 不能调用类的任何构造方法 .
3. 如果此类引用了其他类或者关联了其他类 , 则在序列化时 , 将同时序列化它所引用的类 .
六 . Serializable 接口下控制序列化行为
1. 实现 Serializable 接口 , 并提供 private void writeObject(Object obj),private void readObject() 方法 . 如果需要默认序列化方法或者默认反序列化方法 , 则可以在这两个方法中调用 ObjectOutputStream 的 defaultWriteObject() 方法或者 ObjectOutputStream 的 defaultReadObject() 方法
2. 如何确定需要用户自定义序列化方式 , 从而控制序列化的行为 , 如下所示 :
> 确保序列化的安全性 , 对敏感信息的隐藏者加密 . 如果序列化加密 , 则反序列化时要解密 .
> 确保对象的成员变量符合正解的约束条件
> 优化序列化的性能 . 主要是避免过多序列化类的关联类 .
> 便于更好地封装类的内部数据 , 确保类的接口不会被类的内部实现所约束 .
七 . 实现 Externalizable 接口
1. 实现此接口的类必须自己控制序列化和反序列化时的行为 . 因此必须实现 public void writeExternal(ObjectOutput out) 方法和 public void readExtername() 方法 . 在对实现了 Externalizable 接口的类进行反序列化时 , 会先调用类的不带参数的构造方法 , 这是有别于默认反序列化方式的 . 所以类必须要有一个 public 访问权限的不带参数的构造方法 .
八 . 可序列化类的不同版本的序列化兼容性
对于同一个类的两个不同版本 , 即便它们的序列化版本号相同 , 也不一定能兼容 . 因为兼容性不仅取决于序列化版本号 , 还取决于类的不同版本的实现细节和序列化细节 .