序列化与反序列化
对序列化与反序列化的图解
序列化与反序列化的含义
序列化:将内存中的java对象及其数据保存到硬盘上的过程
反序列化:将硬盘上保存的java对象恢复到内存中成为java对象
通过ObjectOutputStream流序列化java对象
- 构造方法 ObjectOutputStream(OutputStream out)创建流对象(该流是一个包装流,参数需要传入一个节点流)
- 调用writerObject(Object obj)即可将obj对象写出去
注意:序列化的目标类需要实现Serializable接口,表明该类可以被序列化,否则会报NotSerializableException异常
java中如何区分不同类?
- 通过类名
- 类名相同,通过序列化版本号
Serializable和序列化版本号的作用??
Serializable是一个标志接口,内容为空,实现这个接口时不需要实现其方法。
这个接口是给java虚拟机看的,JVM看到实现了Serializable接口则默认为其分配一个序列化版本号serialVersionUID
java源文件编译后会生成一个序列化版本号,如果改动了这个源文件,那么再次编译后将会生成一个新的序列化版本号,在反序列化的时候会再生成一个序列化版本号与之前的进行对比,如果相同则反序列化成功,否则失败。改动后重新生成的序列化版本号与反序列化生成的版本号肯定不相同了,于是会出现InvalidClassException无效类异常。自动生成序列化版本号的缺点:
一旦程序编译后,就不能再修改了。因为一旦修改后必然再次编译,JVM会将其视为一个新的java类,为其分配一个新的序列化版本号。这样违背了我们的逻辑认知。
对于序列化版本号的结论:
一般来说,对于实现了Serializable接口的类,我们需要给其提供一个固定的序列化版本号,不使用JVM默认分配的。如此一来,即使修改了代码重新编译,JVM会将其识别为同一个类了。
例如:public static final long SerialVersionUID=1L
通过ObjectInputStream流反序列化
- 构造方法 ObjectInputStream(InputStream in)创建流对象(该流是一个包装流,参数需要传入一个节点流)
- 调用readObject()即可将对象读进来
序列化多个对象
将多个对象放入集合中,对集合进行序列化。
不能一个一个序列化,否则会报错
transient游离关键字
如果不想某个属性参与序列化,则在其修饰符中加入transient即可