文章目录
先抛出序列化相关几个面试问题,各位看看能否答得上来?
- Java序列化机制的意义是什么?
- 你知道哪些序列化技术?
- 如何自定义序列化内容?
- serialVersionUID有什么用?
- 静态变量能否序列化?
- 某个字段(比如密码字段)不想序列化的话,怎么办?
- 序列化机制有什么缺点?
- Dubbo中的异常处理机制了解么?为什么要这么设计?
面试题是抛砖引玉,了解其背后原理才是目的,话不多说,发车了
序列化的意义
-
我们在内存中创建可复用的 Java 对象,但一般情况下,只有当 JVM 处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比 JVM 的生命周期更长。但在现实应用中,就可能要求在 JVM 停止运行之后能够保存(持久化)指定的对象,比如将用户数据保存在磁盘中、数据库中,并在将来重新读取被保存的对象。
-
不同Java系统之间经常会有交换数据、通信的需求,但是网络中的数据传输都是以字节流的形式,因此发送方系统有必要把对象数据转化成字节流数据来在网络中传输,而接收方系统接收到字节流后再反序列化成Java对象。Dubbo这种RPC通信框架中,Java对象就必须实现序列化接口。
总得来说:Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。从而达到网络传输、本地存储的效果
- Java序列化机制的意义是什么?已经有了答案
市面上的序列化技术
盗用网上一张图来说明
其中重点提一下JSON和Protobuf, JSON 和 protobuf 之间最显著的区别是 JSON 是基于文本的,并且是人类可读的,而 protobuf 是二进制的,但效率更高;JSON 是一种专门的数据表示,而 protobuf 提供模式(类型)来记录和执行适当的用法。虽然 protobuf 比 JSON 更有效,但是 JSON 对于基于文本的表示非常有效。虽然 protobuf 是一种二进制表示,但它确实提供了另一种文本表示,可用于需要具备人类可读性的场景
- 你知道哪些序列化技术?这里也有了答案
序列化接口Serializable、Externalizable
上面提到了很多序列化技术,当然本文重点是Java中的序列化
Serializable
Java中实现对象的可序列化非常简单,相关Java类实现 Serializable
接口即可,如图所示
@Getter
@Setter
static class User implements Serializable {
//序列化id
private static final long serialVersionUID = 1L;
private Long userId;
private String userName;
}
再来看看把User对象持久化到磁盘,并从磁盘读取后反序列化的例子,可以看到userId、userName被持久化下来,并能成功读取磁盘文件并反序列成Java对象
Externalizable
实现了Serializable
接口的对象,Java已经为我们提供了内置的序列化功能,那么如果想自己自定义实现序列化内容呢,该怎么做?
Externalizable
接口继承自Serializable
接口,同时添加了writeExternal
、readExternal
方法用于实现自定义序列化功能。
修改上述User对象,并实现Externalizable
接口
注意: 使用Externalizable接口的对象必须要有一个无参构造函数
@Getter
@Setter
static class User implements Externalizable {
private static final long serialVersionUID = 1L;
private Long userId;
private String userName;
public User() {
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(userId);
out