Java 序列化
本文最后更新于:2024年3月18日 凌晨
Java 序列化
- Java序列化是将一个对象编码成一个字节流,反序列化将字节流编码转换成一个对象。
- 对象输入流
ObjectInputStream
和对象输出流ObjectOutputStream
将Java流系统扩充到能输入/输出对象,他们提供的writeObject()
和readObject()
方法实现了对象的序列化(Serialized)和反序列化(Deserialized)
Serializable 实现序列化
- 为了实现用户自定义的序列化,相应的类必须实现
Serializable
接口,Serializable
接口中没有定义任何方法在,Java 中实现了 Serializable 接口后, JVM 会在底层帮我们实现序列化和反序列。 - 被 transient 关键字修饰的属性不会被序列化, static 属性也不会被序列化。
serialVersionUID
- Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的,在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。
- 如果不显示指定 serialVersionUID, JVM 在序列化时会根据属性自动生成一个 serialVersionUID,然后与属性一起序列化,再进行持久化或网络传输。在反序列化时, JVM 会再根据属性自动生成一个新版 serialVersionUID,然后将这个新版 serialVersionUID 与序列化时生成的旧版 serialVersionUID 进行比较,如果相同则反序列化成功,否则报错。
- 如果显示指定了 serialVersionUID, JVM 在序列化和反序列化时仍然都会生成一个 serialVersionUID,但值为我们显示指定的值,这样在反序列化时新旧版本的 serialVersionUID 就一致了。
- 当序列化了一个类实例后,希望更改一个字段或添加一个字段,不设置serialVersionUID,所做的任何更改都将导致无法反序化旧有实例,并在反序列化时抛出异常。
使用ObjectStream输入输出对象流
[例13-9]:系统对象的序列化处理。
将系统对象写入文件
1 |
|
读取文件中的对象并显示出来
1 |
|
[例13-10]:利用对象序列化将各种图形元素以对象形式存储,从而实现图形的保存。
- 为简单起见,这里以直线和圆为例,创建Line和Circle两个类分别表示直线和圆,为了能方便地访问各种图形元素,定义一个抽象父类Graph,其中提供了一个
draw()
方法用来绘制相应的图形。
图形对象的序列化设计
1 |
|
测试将图形对象序列化写入文件
1 |
|
从文件读取序列化对象并绘图
1 |
|
- 说明:为了增加程序的通用性,程序中将要写入文件中的图形对象的数量首先写入到文件的开始处。
Externalizable 实现序列化
1 |
|
- content变量会被序列化吗?好吧,我把答案都输出来了,是的,运行结果就是:
1 |
|
- 这是为什么呢,不是说类的变量被transient关键字修饰以后将不能序列化了吗?
- 我们知道在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关,因此第二个例子输出的是变量content初始化的内容,而不是null
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!