生活随笔
收集整理的這篇文章主要介紹了
Java 序列化Serializable详解(附详细例子)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
??Java?序列化Serializable詳解(附詳細(xì)例子)?
1、什么是序列化和反序列化
Serialization(序列化)是一種將對(duì)象以一連串的字節(jié)描述的過程;反序列化deserialization是一種將這些字節(jié)重建成一個(gè)對(duì)象的過程。
2、什么情況下需要序列化?
a)當(dāng)你想把的內(nèi)存中的對(duì)象保存到一個(gè)文件中或者數(shù)據(jù)庫中時(shí)候;
b)當(dāng)你想用套接字在網(wǎng)絡(luò)上傳送對(duì)象的時(shí)候;
c)當(dāng)你想通過RMI傳輸對(duì)象的時(shí)候;
3、如何實(shí)現(xiàn)序列化
將需要序列化的類實(shí)現(xiàn)Serializable接口就可以了,Serializable接口中沒有任何方法,可以理解為一個(gè)標(biāo)記,即表明這個(gè)類可以序列化。
4、序列化和反序列化例子
如果我們想要序列化一個(gè)對(duì)象,首先要?jiǎng)?chuàng)建某些OutputStream(如FileOutputStream、ByteArrayOutputStream等),然后將這些OutputStream封裝在一個(gè)ObjectOutputStream中。這時(shí)候,只需要調(diào)用writeObject()方法就可以將對(duì)象序列化,并將其發(fā)送給OutputStream(記住:對(duì)象的序列化是基于字節(jié)的,不能使用Reader和Writer等基于字符的層次結(jié)構(gòu))。而反序列的過程(即將一個(gè)序列還原成為一個(gè)對(duì)象),需要將一個(gè)InputStream(如FileInputstream、ByteArrayInputStream等)封裝在ObjectInputStream內(nèi),然后調(diào)用readObject()即可。
[java]?view plaincopy
package?com.sheepmu;?? import?java.io.FileInputStream;?? import?java.io.FileNotFoundException;?? import?java.io.FileOutputStream;?? import?java.io.IOException;?? import?java.io.ObjectInputStream;?? import?java.io.ObjectOutputStream;?? import?java.io.Serializable;?? ?? public?class?MyTest?implements?Serializable?? {?? ????private?static?final?long?serialVersionUID?=?1L;?? ????private?String?name="SheepMu";?? ????private?int?age=24;?? ????public?static?void?main(String[]?args)?? ????{?? ????????try??? ????????{?? ????????????ObjectOutputStream?oos?=?new?ObjectOutputStream(new?FileOutputStream("my.out"));?? ????????????MyTest?myTest=new?MyTest();?? ????????????oos.writeObject(myTest);??? ????????????oos.flush();???? ????????????oos.close();??? ????????}?catch?(FileNotFoundException?e)??? ????????{?????????? ????????????e.printStackTrace();?? ????????}?catch?(IOException?e)??? ????????{?? ????????????e.printStackTrace();?? ????????}??? ????????fan();?? ????}?? ????public?static?void?fan()?? ????{?????? ?????????ObjectInputStream?oin?=?null;?? ????????try?? ????????{?? ????????????oin?=?new?ObjectInputStream(new?FileInputStream("my.out"));?? ????????}?catch?(FileNotFoundException?e1)?? ????????{?????????? ????????????e1.printStackTrace();?? ????????}?catch?(IOException?e1)?? ????????{?? ????????????e1.printStackTrace();?? ????????}???????? ????????MyTest?mts?=?null;?? ????????try?{?? ????????????mts?=?(MyTest?)?oin.readObject();?? ????????}?catch?(ClassNotFoundException?e)?{?? ????????????e.printStackTrace();?? ????????}?catch?(IOException?e)?{?? ????????????e.printStackTrace();?? ????????}??????? ?????????System.out.println("name="+mts.name);?????? ?????????System.out.println("age="+mts.age);?????? ????}?? }??
會(huì)在此項(xiàng)目的工作空間生成一個(gè) my.out文件。序列化后的內(nèi)容稍后補(bǔ)齊,先看反序列化后輸出如下:
name=SheepMu
age=24
5、序列化ID
序列化 ID 在 Eclipse 下提供了兩種生成策略,一個(gè)是固定的 1L,一個(gè)是隨機(jī)生成一個(gè)不重復(fù)的 long 類型數(shù)據(jù)(實(shí)際上是使用 JDK 工具生成),在這里有一個(gè)建議,如果沒有特殊需求,就是用默認(rèn)的 1L 就可以,這樣可以確保代碼一致時(shí)反序列化成功。這也可能是造成序列化和反序列化失敗的原因,因?yàn)椴煌男蛄谢痠d之間不能進(jìn)行序列化和反序列化。
6.序列化前和序列化后的對(duì)象的關(guān)系
是 "=="還是equal? or ?是淺復(fù)制還是深復(fù)制??
答案:深復(fù)制,反序列化還原后的對(duì)象地址與原來的的地址不同
序列化前后對(duì)象的地址不同了,但是內(nèi)容是一樣的,而且對(duì)象中包含的引用也相同。換句話說,通過序列化操作,我們可以實(shí)現(xiàn)對(duì)任何可Serializable對(duì)象的”深度復(fù)制(deep copy)"——這意味著我們復(fù)制的是整個(gè)對(duì)象網(wǎng),而不僅僅是基本對(duì)象及其引用。對(duì)于同一流的對(duì)象,他們的地址是相同,說明他們是同一個(gè)對(duì)象,但是與其他流的對(duì)象地址卻不相同。也就說,只要將對(duì)象序列化到單一流中,就可以恢復(fù)出與我們寫出時(shí)一樣的對(duì)象網(wǎng),而且只要在同一流中,對(duì)象都是同一個(gè)。
7.靜態(tài)變量能否序列化
若把上面的代碼中的 age變量前加上 static ,輸出任然是
name=SheepMu
age=24
但是看下面的例子:
[java]?view plaincopy
package?com.sheepmu;?? import?java.io.FileInputStream;?? import?java.io.FileNotFoundException;?? import?java.io.FileOutputStream;?? import?java.io.IOException;?? import?java.io.ObjectInputStream;?? import?java.io.ObjectOutputStream;?? import?java.io.Serializable;?? public?class?MyTest?implements?Serializable?? {?? ????private?static?final?long?serialVersionUID?=?1L;?? ????private?String?name="SheepMu";?? ????private?static?int?age=24;?? ????public?static?void?main(String[]?args)?? ????{?? ????????try??? ????????{?? ????????????ObjectOutputStream?oos?=?new?ObjectOutputStream(new?FileOutputStream("my.out"));?? ????????????MyTest?myTest=new?MyTest();?? ????????????oos.writeObject(myTest);??? ????????????oos.flush();???? ????????????oos.close();??? ????????}?catch?(FileNotFoundException?e)??? ????????{?????????? ????????????e.printStackTrace();?? ????????}?catch?(IOException?e)??? ????????{?? ????????????e.printStackTrace();?? ????????}??? ????????fan();?? ????}?? ????public?static?void?fan()?? ????{?? ????????new?MyTest().name="SheepMu_1";??????? ????????age=1;?????????? ?????????ObjectInputStream?oin?=?null;?? ????????try?? ????????{?? ????????????oin?=?new?ObjectInputStream(new?FileInputStream("my.out"));?? ????????}?catch?(FileNotFoundException?e1)?? ????????{?????????? ????????????e1.printStackTrace();?? ????????}?catch?(IOException?e1)?? ????????{?? ????????????e1.printStackTrace();?? ????????}???????? ????????MyTest?mts?=?null;?? ????????try?{?? ????????????mts?=?(MyTest?)?oin.readObject();?? ????????}?catch?(ClassNotFoundException?e)?{?? ????????????e.printStackTrace();?? ????????}?catch?(IOException?e)?{?? ????????????e.printStackTrace();?? ????????}??????? ?????????System.out.println("name="+mts.name);?????? ?????????System.out.println("age="+mts.age);?????? ????}?? }??
輸出結(jié)果為:
name=SheepMu
age=1
為何把最上面代碼的age變量添上static 后還是反序列化出了24呢?而新的從新對(duì)變量賦值的代碼,不是static的得到了序列化本身的值,而static的則得到的是從新附的值。原因:?序列化會(huì)忽略靜態(tài)變量,即序列化不保存靜態(tài)變量的狀態(tài)。靜態(tài)成員屬于類級(jí)別的,所以不能序列化。即 序列化的是對(duì)象的狀態(tài)不是類的狀態(tài)。這里的不能序列化的意思,是序列化信息中不包含這個(gè)靜態(tài)成員域。最上面添加了static后之所以還是輸出24是因?yàn)樵撝凳?/span>JVM加載該類時(shí)分配的值。注:transient后的變量也不能序列化,但是情況稍復(fù)雜,稍后開篇說。
8、總結(jié):
a)當(dāng)一個(gè)父類實(shí)現(xiàn)序列化,子類自動(dòng)實(shí)現(xiàn)序列化,不需要顯式實(shí)現(xiàn)Serializable接口;
b)當(dāng)一個(gè)對(duì)象的實(shí)例變量引用其他對(duì)象,序列化該對(duì)象時(shí)也把引用對(duì)象進(jìn)行序列化;
c) static,transient后的變量不能被序列化;
from:?http://blog.csdn.net/sheepmu/article/details/27579895
總結(jié)
以上是生活随笔為你收集整理的Java 序列化Serializable详解(附详细例子)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。