04-java序列化
一、序列化含义
序列化: 将对象写入IO流中
反序列化:从IO流中恢复对象
目的: 序列化机制允许将实现序列化的Java对象转换为字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。
使用: 所有在网络上传输的对象/保存到磁盘中的对象必须是可序列化的
二、序列化的实现方式
概述:可通过实现Serializable接口或者Externalizable接口之一处理
2.1 Serializable
2.1.1 Serializable接口是一个标记接口,不用实现任何方法。一旦实现了此接口,该类的对象就是可序列化的。
反序列化并不会调用构造方法。反序列的对象是由JVM自己生成的对象,不通过构造方法生成。
2.1.2 成员是引用的序列化
如果一个可序列化的类的成员不是基本类型,也不是String类型,那这个引用类型也必须是可序列化的;否则,会导致此类不能序列化。
2.1.3 同一对象不会序列化多次
public class WriteTeacher { public static void main(String[] args) throws Exception { try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("teacher.txt"))) { Person person = new Person("路飞", 20); Teacher t1 = new Teacher("雷利", person); Teacher t2 = new Teacher("红发香克斯", person); //依次将4个对象写入输入流 oos.writeObject(t1); oos.writeObject(t2); oos.writeObject(person); oos.writeObject(t2); } } } 依次将t1、t2、person、t2对象序列化到文件teacher.txt文件中。 注意:反序列化的顺序与序列化时的顺序一致。 public class ReadTeacher { public static void main(String[] args) { try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("teacher.txt"))) { Teacher t1 = (Teacher) ois.readObject(); Teacher t2 = (Teacher) ois.readObject(); Person p = (Person) ois.readObject(); Teacher t3 = (Teacher) ois.readObject(); System.out.println(t1 == t2); System.out.println(t1.getPerson() == p); System.out.println(t2.getPerson() == p); System.out.println(t2 == t3); System.out.println(t1.getPerson() == t2.getPerson()); } catch (Exception e) { e.printStackTrace(); } } } //输出结果 //false //true //true //true //true 从输出结果可以看出,Java序列化同一对象,并不会将此对象序列化多次得到多个对象。
2.1.4 Java序列化算法
-
所有保存到磁盘的对象都有一个序列化编码号
-
当程序试图序列化一个对象时,会先检查此对象是否已经序列化过,只有此对象从未(在此虚拟机)被序列化过,才会将此对象序列化为字节序列输出。
-
如果此对象已经序列化过,则直接输出编号即可
-

2.1.5 java序列化算法潜在的问题
由于java序利化算法不会重复序列化同一个对象,只会记录已序列化对象的编号。如果序列化一个可变对象(对象内的内容可更改)后,更改了对象内容,再次序列化,并不会再次将此对象转换为字节序列,而只是保存序列化编号。
2.1.6 可选的自定义序列化
使用transient关键字选择不需要序列化的字段。
使用transient修饰的属性,java序列化时,会忽略掉此字段,所以反序列化出的对象,被transient修饰的属性是默认值。对于引用类型,值是null;基本类型,值是0;boolean类型,值是false。

浙公网安备 33010602011771号