首頁  >  文章  >  类库下载  >  Java 序列化與反序列化

Java 序列化與反序列化

高洛峰
高洛峰原創
2016-10-29 10:56:571633瀏覽

1、什麼是序列化?為什麼要序列化?

    Java 序列化就是指將物件轉換為位元組序列的過程,而反序列化則是只將位元組序列轉換成目標物件的過程。

    我們都知道,在進行瀏覽器訪問的時候,我們看到的文本、圖片、音頻、視頻等都是通過二進制序列進行傳輸的,那麼如果我們需要將Java對象進行傳輸的時候,是不是也應該先將物件進行序列化?答案是肯定的,我們需要先將Java物件進行序列化,然後透過網絡,IO進行傳輸,當到達目的地之後,再進行反序列化獲取到我們想要的對象,最後完成通信。

2、如何實現序列化

  2.1、使用到JDK中關鍵類別 ObjectOutputStream 和ObjectInputStream

    ObjectOutputStream Object:透過使用write()進行二進制方法,將物件寫入二進位方法。

    ObjectInputStream 類別中:透過使用readObject()方法,從輸入流中讀取二進位流,轉換成物件。

 

  2.2、目標物件需要先實作 Seriable介面

  

我們建立一個對程式碼 接號:

public class Student implements Serializable {
    private static final long serialVersionUID = 3404072173323892464L;
    private String name;
    private transient String id;
    private String age;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", id='" + id + '\'' +
                ", age='" + age + '\'' +
                '}';
    }

    public String getAge() {
        return age;
    }

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

    public Student(String name, String id) {
        System.out.println("args Constructor");
        this.name = name;
        this.id = id;
    }

    public Student() {
        System.out.println("none-arg Constructor");
    }

    public String getName() {
        return name;
    }

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

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

}

      首先:

1、Serializable 介面的作用只是用來標識我們這個類別是需要進行序列化,並且Serializable 介面中並沒有提供任何方法。

      2、serialVersionUid 序列化版本號的作用是用來區分我們所寫的類別的版本,用於判斷反序列化時類別的版本是否一直,如果不一致會出現版本不一致異常。


      3、transient       3、transient 關鍵字,主要用來忽略我們不希望進行序列化的變數

 

   3. 1 第一種寫入方式:

private static final long serialVersionUID = 3404072173323892464L;

      建立物件Student ,然後透過ObjectOutputStream類別中的writeObject()方法,將物件輸出到檔案中。

      接著透過ObjectinputStream 類別中的readObject()方法進行反序列化,取得物件。

 

       2.3.2 第二種寫入方式:

在Student 類別中實作writeObject()和readObject()方法:這些順序中

在Student 類別中實作呢化的變量,將輸入流和輸出流傳入對線實例中,然後進行序列化以及反序列化。

  

      2.3.3 第三種寫入方式:

Student 實作 Externalnalizable介面而不實作Serializable 介面

Student 實作 Externalnalizable介面而不實作Serializable 介面

Student 實作 Externalnalizable介面而不實作Serializable 介面

Student 實作 Externalnalizable介面而不實作Serializable 介面

的介面產品『

public static  void main(String[] args){
        File file = new File("D:/test.txt");
        Student student = new Student("孙悟空","12");
        try {
            ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
            outputStream.writeObject(student);
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
            Student s = (Student) objectInputStream.readObject();
            System.out.println(s.toString());
            System.out.println(s.equals(student));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

  通過和前面的第二種寫入方法對比,我們可以發現他們的實作原理都是十分的類似,不過實作Externalnalizable介面 並不支援第一種序列化方法,它只能夠透過實作介面中的writeExternal()和readExternal()方法實現物件的序列化。

 

 

3、面試中關於序列化的問題:

    1、什麼是序列化,如何實現序列化

㟎位序列成序列化為反序號     將二進位序列轉換成物件

        Java 實作序列化有多種方式🀎       Java 實作序列化有多種方式🀎

      『、〜      〜〜 、StreamStream  〜 〜〜 〜〜 〜『Stream 、類兩種工具都需要使用到兩個工具        2、實作Serializable 介面:

                              :

                  2.1 直接透過ObjectOutputStream 和ObjectInputStream 類別中的]]           2.2 透過在序列化物件中實作writeObject()和readObject()方法,傳入ObjectOutputStream和ObjectInputStream對象,完成序列化

          3、實作Externalizable 介面:

                  只能夠透過實作介面中的writeExternal()和readExal(ient   只能夠透過實作介面中的writeExternal()和readEx ) 方法的序列化方法來實現物件的序列化?如何將transient修飾符修飾的變數序列化?
        transient 的作用是用來屏蔽我們不希望進行序列化的變量,是物件在進行序列化和反序列話的過程中忽略該變量。
        我們可以透過上述序列化方法中的 實作writeObject 和readObject 方法,在方法中呼叫輸出流或輸入流的writeUTF()和readUTF()方法。
        或透過實作Externalizable 接口,實作writeExternal()和readExternal()方法,然後再自訂序列話物件。

           3、如何保證序列化和反序列化後的物件一致? (如有異議望指正)
        對於這個問題我在查閱了一些資料之後,發現並不能保證序列化和反序列化之後的對像是一致的,因為我們在反序列化的過程中,是先創建一個一個對象,
        然後再通過對對象進行賦值來完成對象的反序列化,這樣問題就來了,在創建了一個新的對象之後,對象引用和原本的對象並不是指向同一個目標。
        因此我們只能保證他們的資料和版本一致,並不能保證物件一致。


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn