java序列化

本文的參考文章:https://www.cnblogs.com/szlbm/p/5504166.html

平時我們在Java內存中的對象,是無法進行IO操作或者網絡通信的,因爲在進行IO操作或者網絡通信的時候,人家根本不知道內存中的對象是個什麼東西,因此必須將對象以某種方式表示出來,即存儲對象中的狀態。一個Java對象的表示有各種各樣的方式,Java本身也提供給了用戶一種表示對象的方式,那就是序列化。換句話說,序列化只是表示對 象的一種方式而已。

序列化:將一個對象轉換成一串二進制表示的字節數組,通過保存或轉移這些字節數據來達到持久化的目的。

反序列化:將字節數組重新構造成對象。

默認實現序列化的方法:

序列化只需要實現java.io.Serializable接口就可以了。序列化的時候有一個serialVersionUID參數,Java序列化機制是通過在運行時判斷類的serialVersionUID來驗證版本一致性的。 在進行反序列化,Java虛擬機會把傳過來的字節流中的serialVersionUID和本地相應實體類的serialVersionUID進行比較, 如果相同就認爲是一致的實體類,可以進行反序列化,否則Java虛擬機會拒絕對這個實體類進行反序列化並拋出異常。

如果實現 java.io.Serializable接口的實體類沒有顯式定義一個名爲serialVersionUID、類型爲long的變量時,Java序列化 機制會根據編譯的.class文件自動生成一個serialVersionUID,如果.class文件沒有變化,那麼就算編譯再多 次,serialVersionUID也不會變化。

java實現默認的序列化方法就是ObjectOutputStream的defaultWriteObject方法和ObjectInputStream的defaultReadObject方法。

public class SerializableObject implements Serializable
{
    private static final long serialVersionUID = 1L;
    
    private String str0;
    private transient String str1;
    private static String str2 = "abc";
    
    public SerializableObject(String str0, String str1)
    {
        this.str0 = str0;
        this.str1 = str1;
    }
    
    public String getStr0()
    {
        return str0;
    }

    public String getStr1()
    {
        return str1;
    }
}
public static void main(String[] args) throws Exception
{
    File file = new File("D:" + File.separator + "s.txt");
    OutputStream os = new FileOutputStream(file);  
    ObjectOutputStream oos = new ObjectOutputStream(os);
    oos.writeObject(new SerializableObject("str0", "str1"));
    oos.close();
        
    InputStream is = new FileInputStream(file);
    ObjectInputStream ois = new ObjectInputStream(is);
    SerializableObject so = (SerializableObject)ois.readObject();
    System.out.println("str0 = " + so.getStr0());
    System.out.println("str1 = " + so.getStr1());
    ois.close();
}

輸出結果爲:

str0 = str0

str1 = null

原因是:str1被關鍵字transient修飾了,所以他並沒有被序列化,所以結果爲null。

Java中transient關鍵字的作用,簡單地說,就是讓某些被修飾的成員屬性變量不被序列化,這一看好像很好理解,就是不被序列化,那麼什麼情況下,一個對象的某些字段不需要被序列化呢?如果有如下情況,可以考慮使用關鍵字transient修飾:

1、類中的字段值可以根據其它字段推導出來,如一個長方形類有三個屬性:長度、寬度、面積(示例而已,一般不會這樣設計),那麼在序列化的時候,面積這個屬性就沒必要被序列化了;

2、看具體業務需求;

其目的主要是節省存儲空間。可能還有壞處(有些字段可能需要重新計算,初始化什麼的),總的來說,利大於弊。

進行序列化、反序列化時,虛擬機會首先試圖調用對象裏的writeObjectreadObject方法,進行用戶自定義的序列化和反序列化。如果沒有這 樣的方法,那麼默認調用的是ObjectOutputStream的defaultWriteObject以及ObjectInputStream的 defaultReadObject方法。換言之,利用自定義的writeObject方法和readObject方法,用戶可以自己控制序列化和反序列 化的過程。

具體實現參考文章:https://www.cnblogs.com/szlbm/p/5504166.html

序列化的學習就解釋了爲什麼我在做springboot項目的過程中需要將javabean實現序列化接口Serializable,其目的就是爲了對象信息能在網絡中傳輸。

 

更多參考資料:https://www.cnblogs.com/chenpi/p/6185773.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章