什么是序列化与反序列化
面试官问这个,大概率不是想听教科书定义,而是想看你能不能把基础概念和实际场景串起来,顺便探探你对坑的理解。
🔹 先用人话翻译一下
序列化就是把内存里活蹦乱跳的对象(带着一堆字段、引用、状态)拍扁,变成一串字节流或者文本,方便存到磁盘、丢进网络。
反序列化就是把这个字节流重新吹口气,在内存里还原出一个状态一致的对象。
就像你玩拼图:序列化是把拼好的图拆成一块块装进盒子;反序列化是按编号把碎片再拼成原图。
🔹 技术上到底在存什么
它存的不是代码逻辑,而是数据——对象的“值”和“结构”:
-
对象的类信息(哪个类的实例)
-
对象的内部状态(字段名、字段值)
-
对象之间的引用关系(A 引用了 B,B 又引回 A,不能死循环)
所以序列化不等于简单的 toString,它是带结构、带类型元数据的数据抽取。
🔹 最常见的用途
-
网络传输:RPC 调用时,参数和返回值要先序列化成二进制流发出去,另一端反序列化回来。
-
持久化存储:把 session、缓存对象存到 Redis 或文件里,下次重启还能读出来。
-
深拷贝:先序列化再反序列化,直接得到一个全新的、值相同的对象,断掉所有引用关系。
-
消息队列:消息体必须序列化才能在 Kafka/RabbitMQ 里流转。
🔹 一个容易翻车的细节:序列化≠编码
很多人以为 JSON 序列化就是把对象转成 JSON 字符串,这没错,但严格来说 JSON 是数据交换格式,序列化格式有很多种(Java 原生二进制、JSON、XML、Protobuf、Hessian)。不同格式对“类型保真度”不一样。
比如 Java 原生序列化能完美保留继承关系、循环引用;JSON 碰到循环引用直接就 TypeError,而且不管你原来的类结构多复杂,一过 JSON 只剩基本结构和基本类型。
🔹 面试时怎么答显得有深度
我会用三个词总结序列化要解决的核心矛盾:
-
语义保真:还原的对象状态必须和原来一样,不能丢引用关系。
-
跨平台/跨语言:Java 对象序列化后,C++ 能不能读?所以才有 Protobuf、Avro 这些语言无关方案。
-
安全边界:反序列化是最危险的入口之一,你永远不知道字节流里夹带了什么“私货”。所以才有 fastjson 那些血案,所以 Java 官网也早把原生序列化标记为“有风险的历史技术”。
🔹 一个有趣的比喻帮你记住
序列化像给对象开一张“快递单”,上面列了:
-
收件人(类名)
-
包裹里有什么(字段值)
-
关联包裹编号(对象引用)
反序列化就是快递到了之后,按单子拆包,把东西复原摆好。
但如果有人伪造了快递单(恶意反序列化),你就可能收到一个炸弹。
这东西单独问很“八股”,但一结合你实际用过的 RPC 框架、缓存方案、踩过的坑来讲,立刻就不一样了。面试官想听的就是你能从内存里那个活的对象,一直聊到线上因为序列化版本号不一致蹦出来的 InvalidClassException。