序列化:是指将Java对象转换为二进制数据。
反序列化:将二进制数据转换为Java对象。
与序列化功能相关的类有:
- java.io.Serializable;
- java.io.ObjectOutputStream(用于序列化)
- java.io.ObjectInputStream(用于反序列化)
序列化对象的前提:
- 该对象所属的类实现了 java.io.Serializable 接口
- 该类的成员变量中有一个是序列化id
反序列化对象的前提:
- 反序列化对象类也需要实现 java.io.Serializable 接口
序列化端和反序列化端,序列化对象类和反序列化对象类
- 两者的类名,包名需要保持一致。否则反序列化时会抛出java.lang.ClassCastException异常。
- 两者的序列化id需要保持一致。否则反序列化时会抛出java.io.InvalidClassException异常。
- 两者中的成员变量名保持一致。
当然,反序列化对象类可以包含额外的成员变量,也可以不包含序列化对象类中的成员变量,只不过这样就无法读取到该成员变量的值。
序列化对象机制的特点
- 序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量。
- 如果想父类对象也序列化,就需要让父类也实现 Serializable 接口。
- 实现 Serializable 接口的类,Array,enum 都能能被序列化。
序列化对象加密传输
服务器端给客户端发送序列化对象数据,对象中有一些数据是敏感的,比如密码字符串等,希望对该密码字段在序列化时,进行加密,而客户端如果拥有解密的密钥,只有在客户端进行反序列化时,才可以对密码进行读取,这样可以一定程度保证序列化对象的数据安全。
Java序列化提供的解决方案:
在序列化过程中,虚拟机会试图调用对象类里的 writeObject 和 readObject 方法,进行用户自定义的序列化和反序列化,如果没有这样的方法,则默认调用是 ObjectOutputStream 的 defaultWriteObject 方法以及 ObjectInputStream 的 defaultReadObject 方法。用户自定义的 writeObject 和 readObject 方法可以允许用户控制序列化的过程,比如可以在序列化的过程中动态改变序列化的数值。
示例:
项目A:序列化对象类:
package com.java.serializable; import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.io.ObjectOutputStream; import java.io.ObjectOutputStream.PutField; import java.io.Serializable; public class Class03 implements Serializable { // 序列化 ID private static final long serialVersionUID = 1L; // 序列化时不加密 private String name; // 序列化时加密 private String password="initValue"; // 测试temp是否也能被自动序列化 private String temp = "test value of temp"; // 以下省略setter、getter方法 private void writeObject(ObjectOutputStream oos) { try { PutField fields = oos.putFields(); fields.put("password", encrypt(this.password)); fields.put("name", this.name); oos.writeFields(); } catch (Exception e) { e.printStackTrace(); } } // 将参数加密 private String encrypt(String pwd) { return "encryptValue"; } }