1、前言java
複習Java基礎知識點的序列化與反序列化過程,整理了以下學習筆記。數據庫
2、爲何須要序列化與反序列化網絡
程序運行時,只要須要,對象能夠一直存在,而且咱們能夠隨時訪問對象的一些狀態信息,若是程序終止,那麼對象是確定不會存在的,可是有時候,咱們須要在程序終止時保存對象的狀態信息,以後程序再次運行時能夠從新恢復到以前的狀態,如,玩家玩遊戲退出時,須要保存玩家的狀態信息(如等級、裝備等等),以後玩家再此登入時,必需要恢復這些狀態信息。咱們能夠經過數據庫手段來達到這個保存狀態的目的,在Java中,咱們有更簡便的方法進行處理,那就是序列化與反序列化。序列化是一種對象持久化的手段,反序列化與序列化相反,其是經過序列化後的信息從新組裝成對象。序列化與反序列化廣泛應用在網絡傳輸、RMI等場景中。ide
3、序列化概述函數
3.1 序列化類結構圖學習
下面展現了與序列化相關的類的結構圖測試
說明:虛線框的表示接口類型,實線框表示具體的類。this
3.2 序列化關鍵字說明.net
與序列化相關的關鍵字以下3d
說明:
1. 關鍵字transient,用來修飾字段,表示此字段在默認序列化過程當中不會被處理,可是能夠採用另外的手段進行處理。
2. 關鍵字serialVersionUID,表示序列化版本號,當兩個類的序列化ID一致時容許反序列化,默承認以採用編譯器提供的值1L。
3.3 序列化方法說明
與序列化相關的方法以下
說明:writeObject與readObject方法分別在ObjectOutput接口與ObjectInput接口中聲明,在ObjectOutputStream與ObjectInputStream中實現。
4、Serializable
4.1 Serializable定義
Serializable定義以下
public interface Serializable { }
說明:Serializable爲一個接口,而且沒有任何字段和方法,僅僅做爲一個標識。
4.2 使用說明
當序列化對象時,只須要將對象標記爲可序列化,即實現接口Serializable便可。下面的Person類實現了Serializable接口。
package com.hust.grid.leesf.serializable; import java.io.Serializable; public class Person implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String name; private String gender; private int age; private transient Person friend; public Person() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person getFriend() { return friend; } public void setFriend(Person friend) { this.friend = friend; } @Override public String toString() { return "name = " + name + ", gender = " + gender + ", age = " + age + ", friend info is [" + friend + "]"; } }
Person類的friend字段設置爲transient,代表不會被序列化,定義完Person類以後,咱們便可以對Person類進行序列化與反序列化操做了,具體代碼以下
package com.hust.grid.leesf.serializable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializableDemo { public static void main(String[] args) throws Exception { Person leesf = new Person(); Person dyd = new Person(); leesf.setAge(24); leesf.setGender("man"); leesf.setName("leesf"); dyd.setAge(24); dyd.setGender("woman"); dyd.setName("dyd"); leesf.setFriend(dyd); dyd.setFriend(null); File file = new File("test"); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject(leesf); oos.flush(); oos.close(); System.out.println(leesf); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); leesf = (Person) ois.readObject(); ois.close(); System.out.println(leesf); } }
運行結果以下
name = leesf, gender = man, age = 24, friend info is [name = dyd, gender = woman, age = 24, friend info is [null]] name = leesf, gender = man, age = 24, friend info is [null]
說明:因爲friend字段標記爲transient,則默認序列化操做時不會進行序列化,反序列化後其值爲null。
4.3 問題說明
1. Person類不實現Serializable接口
若Person類不實現Serializable接口,進行序列化時,會發生什麼,會出現以下異常。
Exception in thread "main" java.io.NotSerializableException:****
表示Person沒有實現Serializable接口,具體緣由以下
在調用writeObject方法後,會通過一系列的調用,具體的調用棧以下
說明:截取了writeObject0函數中的一段代碼,能夠看到會檢查該對象是不是Serializable類型,不是,則會拋出異常。
2. 處理transient對象
當字段被transient修飾時,採用默認的序列化機制將不會對其進行處理,可是,若是要序列化transient字段時,如何作呢,能夠在要進行序列化的類中添加writeObject和readObject方法,其方法簽名以下
private void writeObject(ObjectOutputStream stream) throws IOException private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException
說明:注意,writeObject與readObject是採用private修飾符修飾的,說明,此方法只能在該類的其餘方法中被調用,其餘類中不能調用此方法,那麼當調用ObjectOutputStream的writeObject方法時,如何調用到此方法來執行用戶自定義處理邏輯的呢,答案是反射。利用反射能夠在別的類中調用到此類中私有的方法,反射很強大。
利用這個方法,咱們修改Person類以下
package com.hust.grid.leesf.serializable; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class Person implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String name; private String gender; private int age; private transient Person friend; public Person() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person getFriend() { return friend; } public void setFriend(Person friend) { this.friend = friend; } @Override public String toString() { return "name = " + name + ", gender = " + gender + ", age = " + age + ", friend info is [" + friend + "]"; } private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); stream.writeObject(friend); } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); friend = (Person) stream.readObject(); } }
測試類的代碼不作修改,運行結果以下
name = leesf, gender = man, age = 24, friend info is [name = dyd, gender = woman, age = 24, friend info is [null]] name = leesf, gender = man, age = 24, friend info is [name = dyd, gender = woman, age = 24, friend info is [null]]
說明:在實現自定義的邏輯時,在writeObject方法中能夠調用defaultWriteObject()方法實現默認序列化(序列化非transient字段),能夠單獨處理transient關鍵字;在readObject方法中能夠調用defaultReadObject()方法實現默認反序列化,能夠單獨處理transient關鍵字(須要賦值)。值得注意的是,writeObject方法中defaultWriteObject和處理transient關鍵字的邏輯必須與readObject中defaultReadObject和處理transient關鍵字的邏輯順序一致,不然會拋出異常。
在調用writeObject方法後,會通過一系列的調用,具體的調用棧以下
說明:通過反射,最終會調用到在Person類中定義的writeObject方法。readObject方法的調用能夠以此類比,再也不累贅。
5、Externalizable
除了使用Serializable接口進行序列化之外,還可使用Externalizable接口來進行序列化。
5.1 Externalizable定義
Externalizable的定義以下
public interface Externalizable extends java.io.Serializable { void writeExternal(ObjectOutput out) throws IOException; void readExternal(ObjectInput in) throws IOException, ClassNotFoundException; }
說明:Externalizable實現了Serializable接口,而且添加了兩個方法writeExternal與readExternal,須要序列化的類須要實現Externalizable接口,而且重寫接口中定義的兩個方法。
5.2 使用說明
首先將序列化的類實現Externalizable接口而且重寫writeExternal與readExternal方法,並在這兩個方法中實現處理邏輯。咱們定義Person類以下
package com.hust.grid.leesf.serializable; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; public class Person implements Externalizable { /** * */ private static final long serialVersionUID = 1L; private String name; private String gender; private int age; private transient Person friend; public Person() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person getFriend() { return friend; } public void setFriend(Person friend) { this.friend = friend; } @Override public String toString() { return "name = " + name + ", gender = " + gender + ", age = " + age + ", friend info is [" + friend + "]"; } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeUTF(name); out.writeUTF(gender); out.writeInt(age); out.writeObject(friend); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name = in.readUTF(); gender = in.readUTF(); age = in.readInt(); friend = (Person) in.readObject(); } }
說明:Person類實現了Externalizable接口,重寫了writeExternal與readExternal方法,而且實現了用戶自定義序列化與反序列化邏輯。測試類代碼不變,運行結果以下:
name = leesf, gender = man, age = 24, friend info is [name = dyd, gender = woman, age = 24, friend info is [null]] name = leesf, gender = man, age = 24, friend info is [name = dyd, gender = woman, age = 24, friend info is [null]]
說明:從結果可知,成功進行了序列化與反序列化過程。值得注意的是,咱們必需要給Person類提供一個無參構造器,才能正確完成序列化與反序列化過程。不然會拋出以下異常
修改Person類以下
package com.hust.grid.leesf.serializable; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; public class Person implements Externalizable { /** * */ private static final long serialVersionUID = 1L; private String name; private String gender; private int age; private transient Person friend; public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person getFriend() { return friend; } public void setFriend(Person friend) { this.friend = friend; } @Override public String toString() { return "name = " + name + ", gender = " + gender + ", age = " + age + ", friend info is [" + friend + "]"; } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeUTF(name); out.writeUTF(gender); out.writeInt(age); out.writeObject(friend); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name = in.readUTF(); gender = in.readUTF(); age = in.readInt(); friend = (Person) in.readObject(); } }
說明:提供一個參數的構造函數,沒有無參構造函數,修改測試類代碼以下
package com.hust.grid.leesf.serializable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializableDemo { public static void main(String[] args) throws Exception { Person leesf = new Person("leesf"); Person dyd = new Person("dyd"); leesf.setAge(24); leesf.setGender("man"); leesf.setName("leesf"); dyd.setAge(24); dyd.setGender("woman"); dyd.setName("dyd"); leesf.setFriend(dyd); dyd.setFriend(null); File file = new File("test"); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject(leesf); oos.flush(); oos.close(); System.out.println(leesf); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); leesf = (Person) ois.readObject(); ois.close(); System.out.println(leesf); } }
運行結果以下
name = leesf, gender = man, age = 24, friend info is [name = dyd, gender = woman, age = 24, friend info is [null]] Exception in thread "main" java.io.InvalidClassException: com.hust.grid.leesf.serializable.Person; no valid constructor at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:150) at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:768) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1775) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at com.hust.grid.leesf.serializable.SerializableDemo.main(SerializableDemo.java:32)
說明:在反序列化的過程拋出了異常,能夠看出是Person類沒有合法的構造器,合法的構造器就是指無參構造器。當提供了無參構造器以後,就能夠正確運行。
5.3 問題說明
1. Externalizable,writeObject與readObject方法
若是Person類實現了Externalizable接口,而且在Person類中添加了writeObject與readObject方法,那麼在進行序列化與反序列化時,是以哪一種方法爲準呢,修改Person類以下
package com.hust.grid.leesf.serializable; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; public class Person implements Externalizable { /** * */ private static final long serialVersionUID = 1L; private String name; private String gender; private int age; private transient Person friend; public Person() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person getFriend() { return friend; } public void setFriend(Person friend) { this.friend = friend; } @Override public String toString() { return "name = " + name + ", gender = " + gender + ", age = " + age + ", friend info is [" + friend + "]"; } @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println("use writeExternal method"); out.writeUTF(name); out.writeUTF(gender); out.writeInt(age); out.writeObject(friend); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("use readExternal method"); name = in.readUTF(); gender = in.readUTF(); age = in.readInt(); friend = (Person) in.readObject(); } private void writeObject(ObjectOutputStream stream) throws IOException { System.out.println("use writeObject method"); stream.defaultWriteObject(); stream.writeObject(friend); } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { System.out.println("use readObject method"); stream.defaultReadObject(); friend = (Person) stream.readObject(); } }
說明:在方法中添加了打印語句,這樣就能夠輕易判別採用的何種方式。測試類代碼以下
package com.hust.grid.leesf.serializable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializableDemo { public static void main(String[] args) throws Exception { Person leesf = new Person(); Person dyd = new Person(); leesf.setAge(24); leesf.setGender("man"); leesf.setName("leesf"); dyd.setAge(24); dyd.setGender("woman"); dyd.setName("dyd"); leesf.setFriend(dyd); dyd.setFriend(null); File file = new File("test"); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject(leesf); oos.flush(); oos.close(); System.out.println(leesf); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); leesf = (Person) ois.readObject(); ois.close(); System.out.println(leesf); } }
運行結果
use writeExternal method use writeExternal method name = leesf, gender = man, age = 24, friend info is [name = dyd, gender = woman, age = 24, friend info is [null]] use readExternal method use readExternal method name = leesf, gender = man, age = 24, friend info is [name = dyd, gender = woman, age = 24, friend info is [null]]
說明:從結果能夠看出,是以Externalizable接口中定義的兩個方法進行序列化與反序列化的,這時,讀者可能又會有另一個疑問,那就是爲何會打印兩次呢?答案是由於該方法被調用了兩次,由於Person類有一個Person域,會致使調用兩次。
2. 處理transient字段
能夠在writeExternal與readExternal方法中實現自定義邏輯,對transient字段進行序列化與反序列化。
6、序列化問題
6.1 採用默認序列化機制,類的靜態字段會被序列化嗎?
採用默認序列化機制進行序列化時,類的靜態字段會被序列化嗎,此時類的靜態字段不會被序列化,固然,咱們能夠採用自定義序列化邏輯對靜態變量進行序列化。
6.2 父類序列化問題
採用默認序列化機制序列化子類時,其父類的字段會被序列化嗎?能夠分爲以下情形
1. 父類沒有實現Serializable接口,沒有提供默認構造函數
這時,反序列化會出錯,提示沒有提供正確的構造函數。修改Person類,代碼以下
package com.hust.grid.leesf.serializable; import java.io.Serializable; class Human { private int number; public Human(int number) { this.number = number; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public String toString() { return "number = " + number; } } public class Person extends Human implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String name; private String gender; private int age; private transient Person friend; public Person(int number, String name) { super(number); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person getFriend() { return friend; } public void setFriend(Person friend) { this.friend = friend; } @Override public String toString() { return super.toString() + ", name = " + name + ", gender = " + gender + ", age = " + age + ", friend info is [" + friend + "]"; } }
測試類的的代碼以下
package com.hust.grid.leesf.serializable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializableDemo { public static void main(String[] args) throws Exception { Person leesf = new Person(1, "leesf"); Person dyd = new Person(2, "dyd"); leesf.setAge(24); leesf.setGender("man"); leesf.setName("leesf"); dyd.setAge(24); dyd.setGender("woman"); dyd.setName("dyd"); leesf.setFriend(dyd); dyd.setFriend(null); File file = new File("test"); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject(leesf); oos.flush(); oos.close(); System.out.println(leesf); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); leesf = (Person) ois.readObject(); ois.close(); System.out.println(leesf); } }
運行結果
number = 1, name = leesf, gender = man, age = 24, friend info is [number = 2, name = dyd, gender = woman, age = 24, friend info is [null]] Exception in thread "main" java.io.InvalidClassException: com.hust.grid.leesf.serializable.Person; no valid constructor at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:150) at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:768) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1775) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at com.hust.grid.leesf.serializable.SerializableDemo.main(SerializableDemo.java:32)
說明:能夠看出是沒有提供合法的構造函數。
2. 父類沒有實現Serializable接口,提供默認構造函數
第一步中出現了錯誤,此時,咱們修改Person類,代碼以下
package com.hust.grid.leesf.serializable; import java.io.Serializable; class Human { private int number; public Human() { } public Human(int number) { this.number = number; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public String toString() { return "number = " + number; } } public class Person extends Human implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String name; private String gender; private int age; private transient Person friend; public Person() { super(); } public Person(int number, String name) { super(number); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person getFriend() { return friend; } public void setFriend(Person friend) { this.friend = friend; } @Override public String toString() { return super.toString() + ", name = " + name + ", gender = " + gender + ", age = " + age + ", friend info is [" + friend + "]"; } }
說明:給Human類提供了無參構造函數。測試類代碼不變,運行結果以下
number = 1, name = leesf, gender = man, age = 24, friend info is [number = 2, name = dyd, gender = woman, age = 24, friend info is [null]] number = 0, name = leesf, gender = man, age = 24, friend info is [null]
說明:此時,咱們能夠看到,能夠進行反序列化了,可是父類的number字段被賦值爲int的默認值0,Person類的transient字段沒有被序列化。
3. 父類實現Serializable接口
當父類實現Serializable接口時,修改Person類代碼以下
package com.hust.grid.leesf.serializable; import java.io.Serializable; class Human implements Serializable { /** * */ private static final long serialVersionUID = 1L; private int number; public Human() { } public Human(int number) { this.number = number; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public String toString() { return "number = " + number; } } public class Person extends Human implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String name; private String gender; private int age; private transient Person friend; public Person() { super(); } public Person(int number, String name) { super(number); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person getFriend() { return friend; } public void setFriend(Person friend) { this.friend = friend; } @Override public String toString() { return super.toString() + ", name = " + name + ", gender = " + gender + ", age = " + age + ", friend info is [" + friend + "]"; } }
測試類的代碼不變,運行結果以下
number = 1, name = leesf, gender = man, age = 24, friend info is [number = 2, name = dyd, gender = woman, age = 24, friend info is [null]] number = 1, name = leesf, gender = man, age = 24, friend info is [null]
說明:從結果可知,已經能夠進行正確的序列化與反序列化了,子類的transient字段沒有被序列化。
6.3 共享對象序列化問題
當序列化的兩個對象都包含另一個對象的引用時,在反序列化時,另一個對象只會出現一次嗎?修改Person類代碼以下
package com.hust.grid.leesf.serializable; import java.io.Serializable; public class Person implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String name; private String gender; private int age; private transient Person friend; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person getFriend() { return friend; } public void setFriend(Person friend) { this.friend = friend; } }
測試類代碼以下
package com.hust.grid.leesf.serializable; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.List; public class SerializableDemo { @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { Person leesf = new Person("leesf"); Person dyd = new Person("dyd"); Person lr = new Person("lr"); leesf.setAge(24); leesf.setGender("man"); dyd.setAge(24); dyd.setGender("woman"); lr.setAge(25); lr.setGender("man"); leesf.setFriend(dyd); lr.setFriend(dyd); dyd.setFriend(null); List<Person> persons = new ArrayList<Person>(); persons.add(leesf); persons.add(dyd); persons.add(lr); ByteArrayOutputStream bos1 = new ByteArrayOutputStream(); ByteArrayOutputStream bos2 = new ByteArrayOutputStream(); ObjectOutputStream oos1 = new ObjectOutputStream(bos1); oos1.writeObject(persons); oos1.writeObject(persons); ObjectOutputStream oos2 = new ObjectOutputStream(bos2); oos2.writeObject(persons); ByteArrayInputStream bis1 = new ByteArrayInputStream(bos1.toByteArray()); ByteArrayInputStream bis2 = new ByteArrayInputStream(bos2.toByteArray()); ObjectInputStream ois1 = new ObjectInputStream(bis1); ObjectInputStream ois2 = new ObjectInputStream(bis2); List<Person> persons1 = (List<Person>) ois1.readObject(); List<Person> persons2 = (List<Person>) ois1.readObject(); List<Person> persons3 = (List<Person>) ois2.readObject(); System.out.println(persons1); System.out.println(persons2); System.out.println(persons3); } }
運行結果以下
[com.hust.grid.leesf.serializable.Person@7f31245a, com.hust.grid.leesf.serializable.Person@6d6f6e28, com.hust.grid.leesf.serializable.Person@135fbaa4] [com.hust.grid.leesf.serializable.Person@7f31245a, com.hust.grid.leesf.serializable.Person@6d6f6e28, com.hust.grid.leesf.serializable.Person@135fbaa4] [com.hust.grid.leesf.serializable.Person@45ee12a7, com.hust.grid.leesf.serializable.Person@330bedb4, com.hust.grid.leesf.serializable.Person@2503dbd3]
說明:從結果可知,oos1執行的writeObject是向同一個內存空間寫了兩次,從結果可看出,兩次寫入的對象的地址空間都是同樣的,即進行了淺拷貝。而oos2執行的writeObject是向另一個內存空間寫了一次,從結果可看出,由於對象的地址不一樣於以前的對象地址,即採用了深拷貝。
7、總結
寫到這裏,關於Java中的序列化與反序列化機制就已經分析完了,通過這次分析,對序列化機制的認識更加深入。學習一個知識點,就要認認真真,踏踏實實的弄懂一個知識點,寫博客就是一個特別好的方式。謝謝各位園友的觀看~
參考連接
http://blog.csdn.net/jiangwei0910410003/article/details/18989711/
http://www.hollischuang.com/archives/1140