轉帖|行業資訊|編輯:龔雪|2016-06-08 18:03:08.000|閱讀 203 次
概述:java序列化是指把java對象轉換為字節序列的過程,而java反序列化是指把字節序列恢復為java對象的過程。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
在說java序列化的作用之前,先說下什么是java序列化吧。java序列化是指把java對象轉換為字節序列的過程,而java反序列化是指把字節序列恢復為java對象的過程。java序列化主要有兩個作用:
對象A1序列化成字節序列A的過程,是把一個存在于內存中的對象轉化為一個可以被持久化和網絡傳輸的字節序列的過程,字節序列A反序列化成A2就是逆過程。注意:A1和A2的關系,應該是equals,而不是==(如果包含transient屬性或者自定義了序列化和反序列化方法,可能equals都不是)。
用戶信息類:
package com.podongfeng; import java.io.Serializable; /** * Title: User.class<br> * Description: 用戶信息類<br> * Create DateTime: 2016年04月18日 下午10:20 <br> * * @author podongfeng */ public class User implements Serializable { private static final long serialVersionUID = 9058870178716533905L; public static String TAG = "java"; private String name; private int age; transient private int salary; public User(String name, int age, int salary) { this.name = name; this.salary = salary; this.age = 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 int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}'; } }
序列化和反序列化測試類:
package com.podongfeng; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * Title: SerializableTest.class<br> * Description: 序列化和反序列化測試<br> * Create DateTime: 2016年04月18日 下午10:33 <br> * * @author podongfeng */ public class SerializableTest { public static void main(String[] args) { User user = new User("jack", 20, 10000); System.out.println(user); // 序列化 ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(new FileOutputStream("jack.txt")); oos.writeObject(user); } catch (Exception e) { e.printStackTrace(); } finally { if (oos != null) { try { oos.flush(); oos.close(); } catch (IOException e) { e.printStackTrace(); } } } // 反序列化 ObjectInputStream ois = null; User user2 = null; try { ois = new ObjectInputStream(new FileInputStream("jack.txt")); user2 = (User)ois.readObject(); System.out.println(user2); } catch (Exception e) { e.printStackTrace(); } finally { if (ois != null) { try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } } System.out.println("user equals user2 : " + user.equals(user2)); System.out.println("user == user2 : " + (user == user2)); } }
運行結果:
User{name='jack', age=20, salary=10000} User{name='jack', age=20, salary=0} user equals user2 : false user == user2 : false
Serializable接口是在java序列化中最常用的。一個實體類想要被序列化,只要實現Serializable接口即可,而且并不需要實現任何方法,實現這個接口更像是一種象征性的聲明。其實也并不完全是這樣,當你的實體類實現這個接口的時候,你的IDE(eclipse或者idea)應該會給你一個警告,提示你serialVersionUID這個成員變量,接下來我們就來說說它的作用。serialVersionUID可以理解為類的版本號,只有版本號相同,反序列化才能成功。serialVersionUID可以不顯式設置,那么就會有一個默認的serialVersionUID,這個是通過你的類定義信息計算所得,也就是說,如果這個類進行了修改,就會產生一個不同的serialVersionUID,那么之前序列化的字節流就不能正常反序列化了。但是,在某些情況下,我們對實體類進行了修改,比如增加了一個成員變量,但我還是希望可以反序列成功,其實就可以通過顯示定義一個serialVersionUID,只要增加成員變量的時候沒有修改serialVersionUID,那么之前序列化好的字節流可以被反序列化成新的對象。
實際的開發過程中,可能會有這樣的需求,一個實體類中,某些屬性需要序列化,某些屬性不需要,如果能自己控制,可以有效減少系列化的長度,提高序列化和反序列話的效率。比較便捷的方式是通過transient關鍵字,聲明為transient的成員變量不會被序列化。正如上面樣例代碼中輸出的結果,salary字段被定義為transient,在user對象中有值為10000,但是序列化反序列化后user2對象中salary為0,即int類型的初始值。如果覺得這還不夠,需要進一步自定義,那么可以考慮覆寫writeObject(ObjectOutput out)和readObject(ObjectInput in)方法,如果你的實體類實現了Serializable接口并且覆寫了這2個方法,jvm就會調用這2個方法進行序列化和反序列化了,你可以完全控制需要序列化的屬性和過程了。
除了Serializable接口,想要序列化的類還可以選擇實現Externalizable接口,與writeObject(ObjectOutput out)和readObject(ObjectInput in)方法對應,有這樣2個方法:writeExternal(ObjectOutput out)和readExternal(ObjectInput in)。不同的是,在反序列的過程中,還是調用序列化的類的無參構造方法,而實現Serializable接口并不會。
本文來源:簡書
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn