轉(zhuǎn)帖|行業(yè)資訊|編輯:龔雪|2016-06-08 18:03:08.000|閱讀 203 次
概述:java序列化是指把java對(duì)象轉(zhuǎn)換為字節(jié)序列的過程,而java反序列化是指把字節(jié)序列恢復(fù)為java對(duì)象的過程。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
在說java序列化的作用之前,先說下什么是java序列化吧。java序列化是指把java對(duì)象轉(zhuǎn)換為字節(jié)序列的過程,而java反序列化是指把字節(jié)序列恢復(fù)為java對(duì)象的過程。java序列化主要有兩個(gè)作用:
對(duì)象A1序列化成字節(jié)序列A的過程,是把一個(gè)存在于內(nèi)存中的對(duì)象轉(zhuǎn)化為一個(gè)可以被持久化和網(wǎng)絡(luò)傳輸?shù)淖止?jié)序列的過程,字節(jié)序列A反序列化成A2就是逆過程。注意:A1和A2的關(guān)系,應(yīng)該是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 + '}'; } }
序列化和反序列化測(cè)試類:
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: 序列化和反序列化測(cè)試<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)); } }
運(yùn)行結(jié)果:
User{name='jack', age=20, salary=10000} User{name='jack', age=20, salary=0} user equals user2 : false user == user2 : false
Serializable接口是在java序列化中最常用的。一個(gè)實(shí)體類想要被序列化,只要實(shí)現(xiàn)Serializable接口即可,而且并不需要實(shí)現(xiàn)任何方法,實(shí)現(xiàn)這個(gè)接口更像是一種象征性的聲明。其實(shí)也并不完全是這樣,當(dāng)你的實(shí)體類實(shí)現(xiàn)這個(gè)接口的時(shí)候,你的IDE(eclipse或者idea)應(yīng)該會(huì)給你一個(gè)警告,提示你serialVersionUID這個(gè)成員變量,接下來我們就來說說它的作用。serialVersionUID可以理解為類的版本號(hào),只有版本號(hào)相同,反序列化才能成功。serialVersionUID可以不顯式設(shè)置,那么就會(huì)有一個(gè)默認(rèn)的serialVersionUID,這個(gè)是通過你的類定義信息計(jì)算所得,也就是說,如果這個(gè)類進(jìn)行了修改,就會(huì)產(chǎn)生一個(gè)不同的serialVersionUID,那么之前序列化的字節(jié)流就不能正常反序列化了。但是,在某些情況下,我們對(duì)實(shí)體類進(jìn)行了修改,比如增加了一個(gè)成員變量,但我還是希望可以反序列成功,其實(shí)就可以通過顯示定義一個(gè)serialVersionUID,只要增加成員變量的時(shí)候沒有修改serialVersionUID,那么之前序列化好的字節(jié)流可以被反序列化成新的對(duì)象。
實(shí)際的開發(fā)過程中,可能會(huì)有這樣的需求,一個(gè)實(shí)體類中,某些屬性需要序列化,某些屬性不需要,如果能自己控制,可以有效減少系列化的長(zhǎng)度,提高序列化和反序列話的效率。比較便捷的方式是通過transient關(guān)鍵字,聲明為transient的成員變量不會(huì)被序列化。正如上面樣例代碼中輸出的結(jié)果,salary字段被定義為transient,在user對(duì)象中有值為10000,但是序列化反序列化后user2對(duì)象中salary為0,即int類型的初始值。如果覺得這還不夠,需要進(jìn)一步自定義,那么可以考慮覆寫writeObject(ObjectOutput out)和readObject(ObjectInput in)方法,如果你的實(shí)體類實(shí)現(xiàn)了Serializable接口并且覆寫了這2個(gè)方法,jvm就會(huì)調(diào)用這2個(gè)方法進(jìn)行序列化和反序列化了,你可以完全控制需要序列化的屬性和過程了。
除了Serializable接口,想要序列化的類還可以選擇實(shí)現(xiàn)Externalizable接口,與writeObject(ObjectOutput out)和readObject(ObjectInput in)方法對(duì)應(yīng),有這樣2個(gè)方法:writeExternal(ObjectOutput out)和readExternal(ObjectInput in)。不同的是,在反序列的過程中,還是調(diào)用序列化的類的無參構(gòu)造方法,而實(shí)現(xiàn)Serializable接口并不會(huì)。
本文來源:簡(jiǎn)書
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn