Java序列化通过Serializable接口和ObjectOutputStream/ObjectInputStream实现,1. 实现Serializable标记接口可使对象状态转为字节流,Static和transient字段不被序列化,建议显式声明serialVersionUID避免版本冲突;2. ObjectOutputStream.writeObject()递归写入对象及其非瞬态字段的类元数据和值,支持深度序列化;3. ObjectInputStream.readObject()从字节流重建对象,不调用构造函数,通过反射创建实例并恢复字段值;4. 可定义writeObject、readObject、readResolve和writeReplace等私有方法自定义序列化行为,确保单例或资源正确恢复;类结构变更易引发InvalidClassException,需谨慎管理兼容性。
Java中的序列化和反序列化机制,核心在于将对象的状态信息转换为可存储或传输的形式(如字节流),并在需要时还原为原始对象。这个过程的关键是通过
java.io.Serializable
接口以及ObjectOutputStream和ObjectInputStream类来实现。
1. 序列化的基础:Serializable接口
Serializable是一个标记接口,没有定义任何方法。一个类只要实现了该接口,就表示其对象可以被序列化。jvm会自动处理该类及其非瞬态(non-transient)字段的序列化逻辑。
注意点:
- static字段和用
transient
修饰的字段不会被默认序列化。
- JVM使用字段名、类型和顺序自动生成一个serialVersionUID,用于在反序列化时验证类的一致性。建议显式声明以避免版本不兼容问题。
2. 序列化过程:ObjectOutputStream的作用
当调用
ObjectOutputStream.writeObject()
时,系统会递归遍历对象的所有非瞬态字段,并将其内容写入输出流。
立即学习“Java免费学习笔记(深入)”;
具体流程包括:
- 检查对象是否支持Serializable接口。
- 写入类元数据(如类名、serialVersionUID)。
- 按继承层级从父类到子类依次写入每个可序列化字段的值。
- 如果字段是引用类型,则继续序列化该引用对象(深度序列化)。
3. 反序列化过程:ObjectInputStream的还原机制
调用
ObjectInputStream.readObject()
时,系统从字节流中重建对象实例,但不会调用构造函数。
关键行为:
- 读取类描述符,验证当前JVM中是否存在兼容的类。
- 创建对象实例(通过反射分配内存,绕过构造器)。
- 按字段顺序恢复状态值。
- 对于引用对象,递归完成反序列化并建立引用关系。
4. 自定义序列化逻辑
开发者可以通过定义特定的私有方法控制序列化行为:
-
:在序列化时执行自定义操作。
-
private void readObject(ObjectInputStream in)
:在反序列化时恢复特殊状态(比如重新打开资源)。
-
private Object readResolve()
:用于防止反序列化时破坏单例模式。
-
private Object writeReplace()
:替换将要序列化的对象(例如代理模式)。
基本上就这些。Java序列化依赖于类结构的稳定性,一旦类定义变化(如字段删除或类型变更),可能导致InvalidClassException。因此,在跨版本数据交互中需谨慎管理serialVersionUID和兼容性。
评论(已关闭)
评论已关闭