Serializable介面

ii_chengzi發表於2019-07-15
什麼是java序列化,如何實現?
   序列化就是一種用來處理物件流的機制,所謂物件流也就是將物件的內容進行流化。可以對流化後的物件進行讀寫操作,也可將流化後的物件傳輸於網路之間。
   序列化是為了解決在對 物件進行讀寫操作時所引發的問題。
   序列化的實現:將需要被序列化的類實現Serializable介面,該介面沒有需要被實現的方法,implement Serializable只是為了標註該物件是可被序列化的,然後使用
         一個輸出流(如:fileOutputStream)來構造一個ObjectOutputStream(物件流)物件,接著,使用ObjectOutputStream物件的writeObject方法就可以
         將引數為obj的物件寫出(即儲存其狀態),要恢復的話則利用輸入流。
SerialVersionUID--下面簡稱SUID
其實序列化的作用是能轉化成Byte流,然後又能反序列化成原始的類。能在網路進行傳輸,也可以儲存在磁碟中,有了SUID之後,那麼如果序列化的類已經儲存了在本地中,中途你更改了類後,SUID變了,那麼反序列化的時候就不會變成原始的類了,還會拋異常,主要就是用於版本控制。
SUID:IDE一般會幫你自動生成,其實這個值你可以自己設定,只要保證id值唯一就好。你可以理解成唯一標識。
serialVersionUID是用於記錄class檔案的版本資訊的,serialVersionUID這個數字是透過一個類的類名、成員、包名、工程名算出來的。
使用ObjectInputStream 反序列化的時候,ObjectInputStream會先讀取檔案中的serialVersionUID,然後與本地的class檔案的serialVersionUID進行對比,如果這兩個id不一致,那麼反序列化就失敗了。
物件的輸入輸出流,主要的作用是用於寫物件與讀取物件的資訊。對資訊一旦寫到檔案上那麼物件的資訊就可以持久化了
package com.io.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.*;
import java.util.*;public class Test implements Serializable {//Serializable介面沒有任何方法,只是一個標識介面
    public static void main(String[] args) throws Exception {        new Test().test();
    } 
    private void test() throws FileNotFoundException, IOException, ClassNotFoundException {
        Map<Integer, Film> map = new HashMap<Integer, Film>();
        map.put(1, new Film("變形金剛", 20));
        map.put(2, new Film("鋼鐵俠", 30));
        map.put(3, new Film("復仇者聯盟", 40)); /*,序列化其實就是將film的相關資訊轉化為二進位制儲存在了map.txt這個檔案中,那麼用文字編輯器開啟檢視的話當然是會出現亂碼的。只有透過反序列化才能將儲存的二進位制讀取出來,然後正常顯示在控制檯上。*/
        ObjectOutputStream oos =  new ObjectOutputStream(new FileOutputStream("map.txt"));
        oos.writeObject(map);
        oos.close();         
     /*反序列化*/
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("map.txt"));
        Map<Integer, Film> m = new HashMap<Integer, Film>();
        m = (Map<Integer, Film>) ois.readObject();
        ois.close();
        System.out.println(m.toString());
    }    class Film implements Serializable {        //先執行序列化方法 唯一標識是1L  然後改成2L後   反序列化輸出會報錯
        private static final long serialVersionUID = 1L;        private String name;        private int duration; 
        public Film(String name, int duration) {            this.name = name;            this.duration = duration;
        }        public String getName() {            return name;
        }        public void setName(String name) {            this.name = name;
        }        public int getDuration() {            return duration;
        }        public void setDuration(int duration) {            this.duration = duration;
        }        public Film() {
        }
        @Override        public String toString() {            return "Film{" +                    "name='" + name + '\'' +                    ", duration=" + duration +                    '}';
        }
    }
}

 

物件輸入輸出流要注意的細節

  1. 如果物件需要被寫到檔案上,那麼物件所屬的類必須實現Serializable介面,Serializable介面沒有任何方法,只是一個標識介面。
  2. 物件的反序列化建立物件的時候並不會呼叫到構造方法的。
  3. serialVersionUID是用於記錄class檔案的版本資訊的,serialVersionUID這個數字是透過一個類的類名、成員、包名、工程名算出來的。
  4. 使用ObjectInputStream 反序列化的時候,ObjectInputStream會先讀取檔案中的serialVersionUID,然後與本地的class檔案的serialVersionUID進行對比,如果這兩個id不一致,那麼反序列化就失敗了。
  5. 如果序列化與反序列化的時候可能會修改類的成員,那麼最好一開始就給這個類指定一個serialVersionUID,如果一個類制定了serialVersionUID,然後再序列化和反序列化的時候,jvm都不會再自己算這個serialVersionUID
  6. 如果一個物件某個資料不想被序列化到硬碟上,可以使用關鍵字transient修飾
  7. 如果一個類維護了另外一個類的引用,那麼另外一個類也需要實現Serializable介面
你們都是有經驗的開發人員

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31543790/viewspace-2650544/,如需轉載,請註明出處,否則將追究法律責任。

相關文章