java序列化與反序列化

**序列化和反序列化的概念
把對象轉化爲字節序列的過程稱之爲對象的序列化
反之,稱之爲反序列化

serialVersionUID的作用
如果沒有爲指定的class配置serialVersionUID,那麼java編譯器會自動給這個class進行一個摘要算法,類似於指紋算法,只要這個文件有任何改動,得到的UID就會截然不同的,可以保證在這麼多類中,這個編號是唯一的。所以,由於沒有顯指定 serialVersionUID,編譯器又爲我們生成了一個UID,當然和前面保存在文件中的那個不會一樣了,於是就出現了2個序列化版本號不一致的錯誤。因此,只要我們自己指定了serialVersionUID,就可以在序列化後,去添加一個字段,或者方法,而不會影響到後期的還原,還原後的對象照樣可以使用,而且還多了方法或者屬性可以用。

靜態變量的序列化
序列化並不保存靜態變量的狀態

Transient關鍵字
transient關鍵字表示指定屬性不參與序列化

父子類問題
如果父類沒有實現序列化,而子類實現列序列化。那麼父類中的成員沒辦法做序列化操作

序列化的存儲規則
對同一個對象進行多次寫入,打印出的第一次存儲結果和第二次存儲結果,只多了5個字節的引用關係。
並不會導致文件累加

序列化實現深度克隆
淺拷貝(淺複製、淺克隆):被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。換言之,淺拷貝僅僅複製所拷貝的對象,而不復制它所引用的對象。

深拷貝(深複製、深克隆):被複制對象的所有變量都含有與原來的對象相同的值,除去那些引用其他對象的變量。那些引用其他對象的變量將指向被複制過的新對象,而不再是原有的那些被引用的對象。換言之,深拷貝把要複製的對象所引用的對象都複製了一遍

下面是將一個對象進行序列化和反序列化的例子:

public class Person implements Serializable{
    private static final long serialVersionUID = -2572627257192440740L;

    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public static void main(String[] args) {
        // 序列化操作
        SerializePerson();

        //反序列化操作
        Person person=DeSerializePerson();

        System.out.println(person);
    }

    private static void SerializePerson(){
        try {
            ObjectOutputStream oo=new ObjectOutputStream(new FileOutputStream(new File("person")));
            Person person=new Person();
            person.setAge(18);
            person.setName("test");
            oo.writeObject(person);
            oo.flush();
            System.out.println("序列化成功: "+new File("person").length());
            oo.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private static Person DeSerializePerson(){
        ObjectInputStream ois= null;
        try {
            ois = new ObjectInputStream(new FileInputStream(new File("person")));
            Person person=(Person)ois.readObject();
            return person;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

總結
1.在java中,只要一個類實現了java.io.Serializable接口,那麼它就可以被序列化
2.通過ObjectOutputStream和ObjectInputStream對對象進行序列化合反序列化操作
3. 對象是否允許被反序列化,不僅僅是取決於對象的代碼是否一致,同時還有一個重要的因素(UID)
4. 序列化不保存靜態變量
5. 要想父類對象也參與序列化操作,那麼必須要讓父類也實現Serializable接口
6. Transient關鍵字,主要是控制變量是否能夠被序列化。如果沒有被序列化的成員變量反序列化後,會被設置成初始值,比如String -> null
7. 通過序列化操作實現深度克隆

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