什么是序列化与反序列化
序列化
序列化就是把数据结构或对象转换成二进制串,比如:Java序列化就指把Java对象转换为二进制字节流的过程。
反序列化
反序列化就是把二进制串还原成对象格式,比如:Java反序列化是指把二进制字节流,恢复为Java对象的过程。
为什么需要序列化?
那么为什么要去进行序列化呢?主要有以下两个原因:
第一个原因:持久化
因为对象是存储在JVM中的堆区的,但是如果JVM停止运行了,对象也不存在了。
序列化可以将对象转化成字节序列,可以写进硬盘文件中实现持久化。
第二个原因:网络传输
当两个进程进行远程通信时,可以相互发送各种类型的数据:包括文本、图片、音频、视频等。
但是网络传输数据是无法直接传输数据对象的,所以这些数据对象都会以二进制序列化的形式在网络上传送。
也就是说当两个 Java 进程进行通信时,需要 Java 序列化与反序列化实现进程间的对象传送。
换句话说,一方面,发送方需要把这个 Java 对象转换为字节序列,然后在网络上传送,另一方面,接收方需要从字节序列中恢复出 Java 对象。
总之,序列化最终的目的是为了对象可以跨平台存储和进行网络传输。
Java如何实现序列化?
Java类通过实现Serializable接口来实现该类对象的序列化,如下代码示例:
public class TestBean implements Serializable { private Integer id; private String name; private Date date; //省去getter和setter方法和toString }
什么是Serializable接口
一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才能被序列化。
实现Serializable接口的目的是为类可持久化,比如在网络传输或本地存储,为系统的分布和异构部署提供先决条件。
这个接口非常特殊,没有任何方法,只起标识作用,Java序列化保留了对象类的元数据(如类、成员变量、继承类信息等),以及对象数据等,兼容性最好,但不支持跨语言,而且性能一般。
什么是serialVersionUID
实现Serializable接口的类建议设置serialVersionUID字段值,如果不设置,那么每次运行时,编译器会根据类的内部实现,包括类名、接口名、方法和属性等来自动生成serialVersionUID。
如果类的源代码有修改,那么重新编译后serial VersionUID的取值可能会发生变化。
因此实现Serializable接口的类一定要显式地定义serialVersionUID属性值。
import java.io.Serializable; public class Person implements Serializable{ private static final long serialVersionUID = 1234567890L; private int id; private String name; public Person(int id, String name){ this.id = id; this.name = name; } public String toString(){ return "Person: " + id + " " + name; } }
serialVersionUID的作用
serialVersionUID 是用于在序列化和反序列化过程中进行核验的一个版本号。
序列化与反序列化的例子
1.序列化对象
如下的 SerializeDemo 例子实例化了一个 Employee 对象,并将该对象序列化到一个文件中。
import java.io.*; public class SerializeDemo { public static void main(String [] args) { Employee e = new Employee(); e.name = "mikechen"; e.address = "chengdu"; try { FileOutputStream fileOut = new FileOutputStream("/tmp/employee.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(e); out.close(); fileOut.close(); System.out.printf("Serialized data is saved in /tmp/employee.ser"); }catch(IOException i) { i.printStackTrace(); } } }
2.反序列化对象
import java.io.*; public class DeserializeDemo { public static void main(String [] args) { Employee e = null; try { FileInputStream fileIn = new FileInputStream("/tmp/employee.ser"); ObjectInputStream in = new ObjectInputStream(fileIn); e = (Employee) in.readObject(); in.close(); fileIn.close(); }catch(IOException i) { i.printStackTrace(); return; }catch(ClassNotFoundException c) { System.out.println("Employee class not found"); c.printStackTrace(); return; } System.out.println("Deserialized Employee..."); System.out.println("Name: " + e.name); System.out.println("Address: " + e.address); } }
运行结果如下:
Deserialized Employee... Name: mikechen Address:chengdu
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》