47、序列化和反序列化
阿新 • • 發佈:2018-12-19
在工作中有可能遇到多臺機器遠端通訊的情況,如果要將機器A中的某個java物件傳輸到機器B上面,需要將這個java物件轉換為位元組序列然後進行傳輸。將物件轉換為位元組序列的過程叫做序列化,反之叫做反序列化。
一個物件如果支援序列化,需要實現Serializable的介面,這個介面中沒有任何方法,實現該介面後,JVM會給這個物件做特殊待遇
將java物件儲存到硬盤裡面
使用序列化還可以將一個物件儲存到硬碟中,然後再通過反序列化將該物件讀取到記憶體裡面。
建立一個Student類,實現Serializable介面
package com.monkey1024.serializable;import java.io.Serializable; public class Student implements Serializable { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
使用ObjectOutputStream將Student物件寫出到硬碟中
package com.monkey1024.serializable;import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; /** * 將Student物件序列化到硬碟中 * */ public class ObjectOutput { public static void main(String[] args) { Student s = new Student(); s.setName("張三");// 建立輸出流(序列化流) try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("zhangsan"));) { //將物件寫出到硬碟中 oos.writeObject(s); oos.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
使用ObjectInputStream將硬碟中的物件讀取到記憶體中
package com.monkey1024.serializable; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; /** * 從硬碟中讀取Student物件 * */ public class ObjectInput { public static void main(String[] args) { try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("zhangsan"));) { Student s = (Student)ois.readObject(); System.out.println(s.getName()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
序列化版本號
在一個類實現Serializable介面後,系統會給每個物件一個序列化版本號,當這個類的原始碼被修改後,系統會重新分配一個新的序列化版本號,這樣做的好處就是保證序列化和反序列化的物件內容一致。例如將一個物件序列化到硬碟之後,修改這個物件所對應類的原始碼,在進行反序列化是就會報出InvalidClassException異常。如果手動編寫序列化版本號之後,就不會出現這個異常了。
package com.monkey1024.serializable; import java.io.Serializable; public class Student implements Serializable { /** * 自動生成序列化版本號 */ private static final long serialVersionUID = -716323668524282676L; private String name; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
transient關鍵字
如果不希望將Student類中的age屬性序列化,可以使用transient宣告該屬性,在序列化時將忽略這個屬性。
package com.monkey1024.serializable; import java.io.Serializable; public class Student implements Serializable { /** * 自動生成序列化版本號 */ private static final long serialVersionUID = -716323668524282676L; private String name; //age不序列化 transient private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }