Java序列化與反序列化

1、什麼是序列化與反序列化?

Java 序列化是指把 Java 對象轉換爲字節序列的過程;
Java 反序列化是指把字節序列恢復爲 Java 對象的過程;java

2、爲何要用序列化與反序列化?

爲何要用序列化與反序列化 以前咱們先了解一下對象序列化的兩種用途:api

  1. 把對象的字節序列永久地保存到硬盤上,一般存放在一個文件中;
  2. 在網絡上傳送對象的字節序列。

咱們能夠想一想若是沒有序列化以前,又是怎樣一種情景呢?服務器

舉例:
Web 服務器中的 Session 會話對象,當有10萬用戶併發訪問,就有可能出現10萬個 Session 對象,顯然這種狀況內存多是吃不消的。微信

因而 Web 容器就會把一些 Session 先序列化,讓他們離開內存空間,序列化到硬盤中,當須要調用時,再把保存在硬盤中的對象還原到內存中。網絡


咱們知道,當兩個進程進行遠程通訊時,彼此能夠發送各類類型的數據,包括文本、圖片、音頻、視頻等, 而這些數據都會以二進制序列的形式在網絡上傳送。併發

一樣的序列化與反序列化則實現了 進程通訊間的對象傳送,發送方須要把這個Java對象轉換爲字節序列,才能在網絡上傳送;接收方則須要把字節序列再恢復爲Java對象。app

初步總結:Java 序列化和反序列化,其一,實現了數據的持久化,經過序列化能夠把數據永久的保存在硬盤上;其二,利用序列化實現遠程通訊,即在網絡上傳遞對象的字節序列。工具

3、如何實現序列化與反序列化?

3.1 JDK 類庫中序列化 API

使用到JDK中關鍵類 ObjectOutputStream(對象輸出流) 和ObjectInputStream(對象輸入流)測試

ObjectOutputStream 類中:經過使用 writeObject(Object object) 方法,將對象以二進制格式進行寫入。this

ObjectInputStream 類中:經過使用 readObject()方法,從輸入流中讀取二進制流,轉換成對象。

3.2 目標對象實現 Serializable 接口

咱們建立一個 User 類,實現 Serializable 接口,並生成一個版本號 :

public class User implements Serializable {

    private static final long serialVersionUID = 3604972003323896788L;
    private transient int age;
    private String name;
    private String sex;

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

首先:

一、Serializable 接口的做用只是用來標識咱們這個類是須要進行序列化,而且 Serializable 接口中並無提供任何方法。

二、SerialVersionUid 序列化版本號的做用是用來區分咱們所編寫的類的版本,用於判斷反序列化時類的版本是否一直,若是不一致會出現版本不一致異常。

三、transient 關鍵字,主要用來忽略咱們不但願進行序列化的變量

因爲第一種形式太不常見,顧再也不囉嗦演示,直接來看第二種實現 Serializable 接口的寫入方式:

定義一個Person類,實現Serializable接口

public class Person implements Serializable {

    private static final long serialVersionUID = -5809452578272945389L;
    private int age;
    private String name;
    private String sex;

    get..

    set...
}

序列化和反序列化Person類對象

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.MessageFormat;

/**
 * <p>Description: 測試對象的序列化和反序列<p>
 */

public class TestObjSerializeAndDeserialize {

    public static void main(String[] args) throws Exception {
        SerializePerson();//序列化Person對象
        Person p = DeserializePerson();//反序列Perons對象
        System.out.println(MessageFormat.format("name={0},age={1},sex={2}",
                                                 p.getName(), p.getAge(), p.getSex()));
    }

    /**
     * Description: 序列化Person對象
     */

    private static void SerializePerson() throws FileNotFoundException,
            IOException 
{
        Person person = new Person();
        person.setName("gacl");
        person.setAge(25);
        person.setSex("男");
        // ObjectOutputStream 對象輸出流,將Person對象存儲到E盤的Person.txt文件中,完成對Person對象的序列化操做
        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
                new File("E:/Person.txt")));
        oo.writeObject(person);
        System.out.println("Person對象序列化成功!");
        oo.close();
    }

    /**
     * Description: 反序列Perons對象
     */

    private static Person DeserializePerson() throws Exception, IOException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                new File("E:/Person.txt")));
        Person person = (Person) ois.readObject();
        System.out.println("Person對象反序列化成功!");
        return person;
    }

}

代碼運行結果:

疑問:Person 實體中的 serialVersionUID 是個什麼鬼?

答:序列化版本號,取值是 Java 運行時環境根據類的內部細節自動生成的。若是對類的源代碼做了修改,再從新編譯,新生成的類文件的 serialVersionUID 的取值有可能也會發生變化。。

既然程序幫我門自動生成,那爲什麼還要去定義該屬性?

序列化和反序列化就是經過對比其 SerialversionUID 來進行的,咱們修改一個實現 Serializable 接口的實體類,從新編譯後,顯然程序會從新會生成新值,那麼一旦SerialversionUID 跟以前不匹配,反序列化就沒法成功。

在實際的生產環境中,咱們可能會建一系列的中間 Object 來反序列化咱們的 pojo,爲了解決這個問題,咱們就須要在實體類中自定義 SerialversionUID,就像上方示例,無論咱們序列化以後如何更改咱們的 實體(不刪除原有字段),最終均可以反序列化成功。。

4、總結

什麼是序列化,如何實現序列化?

Java 中對象的序列化就是將對象轉換成二進制序列,反序列化則是將二進制序列轉換成對象。
採用Java序列化與反序列化技術:

  • 一是能夠實現數據的持久化,在MVC模式中非常有用;
  • 二是能夠對象數據的遠程通訊。

Java 實現序列化的多種方式

  1. 首先須要使用到工具類 ObjectInputStream 和ObjectOutputStream 兩個IO類
  2. 實現 Serializable 接口
  3. 實現 Externalizable 接口

若是文章有錯的地方歡迎指正,你們互相留言交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠關注微信公衆號:niceyoo

相關文章
相關標籤/搜索