一個(gè)簡(jiǎn)單的Java序列化的例子
創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),石嘴山企業(yè)網(wǎng)站建設(shè),石嘴山品牌網(wǎng)站建設(shè),網(wǎng)站定制,石嘴山網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,石嘴山網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
import java.io.*;
import java.util.*;
class Data implements Serializable { // 實(shí)現(xiàn)序列話接口
private int n;
public Data(int n) { this.n = n; }
public String toString() { return Integer.toString(n); }
}
public class Worm implements Serializable {
public static void main(String[] args)
throws ClassNotFoundException, IOException { // 序列話讀入和寫入Object可能會(huì)有這兩個(gè)異常
// 將你要序列化的object,保留到一個(gè)文件中
Random rand = new Random();
Data d = new Data(rand.nextInt(10)); //構(gòu)建你需要序列話的Object
System.out.println("d = " + d);
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("worm.out")); // 準(zhǔn)備寫入的文件
out.writeObject(d);
out.flush();
out.close(); // 執(zhí)行到這里你可以看見worm.out這個(gè)文件,
// 以下的代碼讀出你剛剛寫入Object
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("worm.out")); // 讀你剛剛寫入的文件
Data d2 = (Data)in.readObject(); // 重新構(gòu)建你剛剛寫入的Object
System.out.println("d2 = " + d2); }
}
Java中的序列化是把Java對(duì)象轉(zhuǎn)換為字節(jié)序列的過程,能夠?qū)⒁粋€(gè)實(shí)例對(duì)象的狀態(tài)信息寫入到一個(gè)字節(jié)流中,使其可以通過socket進(jìn)行傳輸、或者持久化到存儲(chǔ)數(shù)據(jù)庫(kù)或文件系統(tǒng)中,然后在需要的時(shí)候通過字節(jié)流中的信息來重構(gòu)一個(gè)相同的
dataset使用java的序列化方法:
1、一方面,試圖把RemotingFormat設(shè)置為SerializationFormat.Binary來序列化DataSet。
2、另一方面,也可以簡(jiǎn)單的把那行代碼注釋起來,并且保持默認(rèn)值SerializationFormat.xml。在這種情況下,該例子都是通過計(jì)算執(zhí)行deserialize這樣一個(gè)DataSet操作所需要的時(shí)間來做大致的性能估計(jì)。
壓縮和序列化主要用在數(shù)據(jù)的存儲(chǔ)和傳輸上,二者都是由IO流相關(guān)知識(shí)實(shí)現(xiàn),這里統(tǒng)一介紹下。
全部章節(jié)傳送門:
Java I/O類支持讀寫壓縮格式的數(shù)據(jù)流,你可以用他們對(duì)其他的I/O流進(jìn)行封裝,以提供壓縮功能。
GZIP接口比較簡(jiǎn)單,適合對(duì)單個(gè)數(shù)據(jù)流進(jìn)行壓縮,在Linux系統(tǒng)中使用較多。
ZIP格式可以壓縮多個(gè)文件,而且可以和壓縮工具進(jìn)行協(xié)作,是經(jīng)常使用的壓縮方法。
JAR(Java Archive,Java 歸檔文件)是與平臺(tái)無(wú)關(guān)的文件格式,它允許將許多文件組合成一個(gè)壓縮文件。為 J2EE 應(yīng)用程序創(chuàng)建的 JAR 文件是 EAR 文件(企業(yè) JAR 文件)。
JAR 文件格式以流行的 ZIP 文件格式為基礎(chǔ)。與 ZIP 文件不同的是,JAR 文件不僅用于壓縮和發(fā)布,而且還用于部署和封裝庫(kù)、組件和插件程序,并可被像編譯器和 JVM 這樣的工具直接使用。在 JAR 中包含特殊的文件,如 manifests 和部署描述符,用來指示工具如何處理特定的 JAR。
如果一個(gè)Web應(yīng)用程序的目錄和文件非常多,那么將這個(gè)Web應(yīng)用程序部署到另一臺(tái)機(jī)器上,就不是很方便了,我們可以將Web應(yīng)用程序打包成Web 歸檔(WAR)文件,這個(gè)過程和把Java類文件打包成JAR文件的過程類似。利用WAR文件,可以把Servlet類文件和相關(guān)的資源集中在一起進(jìn)行發(fā)布。在這個(gè)過程中,Web應(yīng)用程序就不是按照目錄層次結(jié)構(gòu)來進(jìn)行部署了,而是把WAR文件作為部署單元來使用。
一個(gè)WAR文件就是一個(gè)Web應(yīng)用程序,建立WAR文件,就是把整個(gè)Web應(yīng)用程序(不包括Web應(yīng)用程序?qū)哟谓Y(jié)構(gòu)的根目錄)壓縮起來,指定一個(gè).war擴(kuò)展名。下面我們將第2章的Web應(yīng)用程序打包成WAR文件,然后發(fā)布
要注意的是,雖然WAR文件和JAR文件的文件格式是一樣的,并且都是使用jar命令來創(chuàng)建,但就其應(yīng)用來說,WAR文件和JAR文件是有根本區(qū)別的。JAR文件的目的是把類和相關(guān)的資源封裝到壓縮的歸檔文件中,而對(duì)于WAR文件來說,一個(gè)WAR文件代表了一個(gè)Web應(yīng)用程序,它可以包含 Servlet、HTML頁(yè)面、Java類、圖像文件,以及組成Web應(yīng)用程序的其他資源,而不僅僅是類的歸檔文件。
在命令行輸入jar即可查看jar命令的使用方法。
把對(duì)象轉(zhuǎn)換為字節(jié)序列的過程稱為對(duì)象的序列化。把字節(jié)序列恢復(fù)為對(duì)象的過程稱為對(duì)象的反序列化。
對(duì)象的序列化主要有兩種用途:
java.io.ObjectOutputStream代表對(duì)象輸出流,它的writeObject(Object obj)方法可對(duì)參數(shù)指定的obj對(duì)象進(jìn)行序列化,把得到的字節(jié)序列寫到一個(gè)目標(biāo)輸出流中。
java.io.ObjectInputStream代表對(duì)象輸入流,它的readObject()方法從一個(gè)源輸入流中讀取字節(jié)序列,再把它們反序列化為一個(gè)對(duì)象,并將其返回。
只有實(shí)現(xiàn)了Serializable的對(duì)象才能被序列化。對(duì)象序列化包括如下步驟:
對(duì)象反序列化的步驟如下:
創(chuàng)建一個(gè)可以可以序列化的對(duì)象。
然后進(jìn)行序列化和反序列化測(cè)試。
serialVersionUID: 字面意思上是序列化的版本號(hào),凡是實(shí)現(xiàn)Serializable接口的類都有一個(gè)表示序列化版本標(biāo)識(shí)符的靜態(tài)變量。
JAVA序列化的機(jī)制是通過判斷類的serialVersionUID來驗(yàn)證的版本一致的。在進(jìn)行反序列化時(shí),JVM會(huì)把傳來的字節(jié)流中的serialVersionUID于本地相應(yīng)實(shí)體類的serialVersionUID進(jìn)行比較。如果相同說明是一致的,可以進(jìn)行反序列化,否則會(huì)出現(xiàn)反序列化版本一致的異常,即是InvalidCastException。
為了提高serialVersionUID的獨(dú)立性和確定性,強(qiáng)烈建議在一個(gè)可序列化類中顯示的定義serialVersionUID,為它賦予明確的值。
控制序列化字段還可以使用Externalizable接口替代Serializable借口。此時(shí)需要定義一個(gè)默認(rèn)構(gòu)造器,否則將為得到一個(gè)異常(java.io.InvalidClassException: Person; Person; no valid constructor);還需要定義兩個(gè)方法(writeExternal()和readExternal())來控制要序列化的字段。
如下為將Person類修改為使用Externalizable接口。
transient修飾符僅適用于變量,不適用于方法和類。在序列化時(shí),如果我們不想序列化特定變量以滿足安全約束,那么我們應(yīng)該將該變量聲明為transient。執(zhí)行序列化時(shí),JVM會(huì)忽略transient變量的原始值并將默認(rèn)值(引用類型就是null,數(shù)字就是0)保存到文件中。因此,transient意味著不要序列化。
靜態(tài)變量不是對(duì)象狀態(tài)的一部分,因此它不參與序列化。所以將靜態(tài)變量聲明為transient變量是沒有用處的。
簡(jiǎn)單來說,如果你只是自己同一臺(tái)機(jī)器的同一個(gè)環(huán)境下使用同一個(gè)JVM來操作,序列化和反序列化是沒必要的,當(dāng)需要進(jìn)行數(shù)據(jù)傳輸?shù)臅r(shí)候就顯得十分必要。比如你的數(shù)據(jù)寫到文件里要被其他人的電腦的程序使用,或者你電腦上的數(shù)據(jù)需要通過網(wǎng)絡(luò)傳輸給其他人的程序使用,像服務(wù)器客戶端的這種模型就是一種應(yīng)用,這個(gè)時(shí)候,大家想想,每個(gè)人的電腦配置可能不同,運(yùn)行環(huán)境可能也不同,字節(jié)序可能也不同,總之很多地方都不能保證一致,所以為了統(tǒng)一起見,我們傳輸?shù)臄?shù)據(jù)或者經(jīng)過文件保存的數(shù)據(jù)需要經(jīng)過序列化和編碼等操作,相當(dāng)于交互雙方有一個(gè)公共的標(biāo)準(zhǔn),按照這種標(biāo)準(zhǔn)來做,不管各自的環(huán)境是否有差異,各自都可以根據(jù)這種標(biāo)準(zhǔn)來翻譯出自己能理解的正確的數(shù)據(jù)。
除了在持久化對(duì)象時(shí)會(huì)用到對(duì)象序列化之外,當(dāng)使用RMI(遠(yuǎn)程方法調(diào)用),或在網(wǎng)絡(luò)中傳遞對(duì)象時(shí),都會(huì)用到對(duì)象序列化。實(shí)現(xiàn)序列化:
1 ? 首先要把準(zhǔn)備要序列化類,實(shí)現(xiàn) Serializabel接口
import?java.io.Serializable;?
public?class?Person?implements?Serializable?{
//本類可以序列化
private?String?name?;?
private?int?age?;
public?Person(String?name,int?age)
{?
this.name?=?name?;?this.age?=?age?;
}?
public?String?toString()
{
return?"姓名:"?+?this.name?+?",年齡"?+?this.age?;
}?
}
2 序列化
package?org.lxh.SerDemo;?
import?java.io.File;
import?java.io.FileOutputStream;?
import?java.io.ObjectOutputStream?;
public?class?ObjectOutputStreamDemo
{
//序列化?
public?static?void?main(String[]?args)?throws?Exception?
{
//序列化后生成指定文件路徑?
File?file?=?new?File("D:"?+?File.separator?+?"person.ser")?;
ObjectOutputStream?oos?=?null?;
//裝飾流(流)
oos?=?new?ObjectOutputStream(new?FileOutputStream(file))?;?
//實(shí)例化類?
Person?per?=?new?Person("張三",30)?;
oos.writeObject(per)?;
//把類對(duì)象序列化
oos.close()?;
}?
}
需要注意的是:
靜態(tài)成員是不能被序列化的,因?yàn)殪o態(tài)成員是隨著類的加載而加載的,與類共存亡,并且靜態(tài)成員的默認(rèn)初始值都是0;就是說靜態(tài)成員屬于類級(jí)別的,所以不能序列化,序列化只是序列化了對(duì)象而已。