序列化和反序列化的作用原理详解

序列化和反序列化的作用原理详解-mikechen

什么是序列化与反序列化

序列化

序列化就是把数据结构或对象转换成二进制串,比如:Java序列化就指把Java对象转换为二进制字节流的过程。

序列化和反序列化的作用原理详解-mikechen

反序列化

反序列化就是把二进制串还原成对象格式,比如:Java反序列化是指把二进制字节流,恢复为Java对象的过程。

序列化和反序列化的作用原理详解-mikechen

 

为什么需要序列化?

那么为什么要去进行序列化呢?主要有以下两个原因:

第一个原因:持久化

因为对象是存储在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面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法