国产18禁黄网站免费观看,99爱在线精品免费观看,粉嫩metart人体欣赏,99久久99精品久久久久久,6080亚洲人久久精品

編程經(jīng)驗(yàn)系列-Java學(xué)習(xí)雜談(四)

時(shí)間:2008-10-06 17:06:00   來(lái)源:無(wú)憂考網(wǎng)     [字體: ]
1.關(guān)于序列化和反序列化
  應(yīng)該大家都大概知道Java中序列化和反序列化的意思,序列化就是把一個(gè)Java對(duì)象轉(zhuǎn)換成二進(jìn)制進(jìn)行磁盤上傳輸或者網(wǎng)絡(luò)流的傳輸,反序列化的意思就是把這個(gè)接受到的二進(jìn)制流重新組裝成原來(lái)的對(duì)象逆過(guò)程。它們?cè)贘ava中分別是通過(guò)ObjectInputStream和 ObjectInputStream這兩個(gè)類來(lái)實(shí)現(xiàn)的(以下分別用ois和oos來(lái)簡(jiǎn)稱)。
  oos的writeObject()方法用來(lái)執(zhí)行序列化的過(guò)程,ois的readObject()用來(lái)執(zhí)行反序列化的過(guò)程,在傳輸二進(jìn)制流之前,需要講這兩個(gè)高層流對(duì)象連接到同一個(gè)Channel上,這個(gè)Channel可以是磁盤文件,也可以是socket底層流。所以無(wú)論用哪種方式,底層流對(duì)象都是以構(gòu)造函數(shù)參數(shù)的形式傳遞進(jìn)oos和ois這兩個(gè)高層流,連接完畢了才可以進(jìn)行二進(jìn)制數(shù)據(jù)傳輸?shù)。例子?br>  可以是文件流通道
  file = new File(“C:/data.dat”);
  oos = new ObjectOutputStream(new FileOutputStream(file));
  ois = new ObjectInputStream(new FileInputStream(file));
  或者網(wǎng)絡(luò)流通道
  oos = new ObjectOutputStream(socket.getOutputStream());
  ois = new ObjectInputStream(socket.getInputStream());
  不知道大家是否注意到oos總是在ois之前定義,這里不希望大家誤解這個(gè)順序是固定的么?回答是否定的,那么有順序要求么?回答是肯定的。原則是什么呢?
  原則是互相對(duì)接的輸入/輸出流之間必須是output流先初始化然后再input流初始化,否則就會(huì)拋異常。大家肯定會(huì)問(wèn)為什么?只要稍微看一看這兩個(gè)類的源代碼文件就大概知道了,output流的任務(wù)很簡(jiǎn)單,只要把對(duì)象轉(zhuǎn)換成二進(jìn)制往通道中寫就可以了,但input流需要做很多準(zhǔn)備工作來(lái)接受并最終重組這個(gè)Object,所以O(shè)bjectInputStream的構(gòu)造函數(shù)中就需要用到output初始化發(fā)送過(guò)來(lái)的header信息,這個(gè)方法叫做 readStreamHeader(),它將會(huì)去讀兩個(gè)Short值用于決定用多大的緩存來(lái)存放通道發(fā)送過(guò)來(lái)的二進(jìn)制流,這個(gè)緩存的size因jre的版本不同是不一樣的。所以output如果不先初始化,input的構(gòu)造函數(shù)首先就無(wú)法正確運(yùn)行。
  對(duì)于上面兩個(gè)例子,第一個(gè)順序是嚴(yán)格的,第二個(gè)因?yàn)閛os和ois連接的已經(jīng)不是對(duì)方了,而是socket另外一端的流,需要嚴(yán)格按照另外一方對(duì)接的output流先于對(duì)接的input流打開(kāi)才能順利運(yùn)行。
  這個(gè)writeObject和readObject本身就是線程安全的,傳輸過(guò)程中是不允許被并發(fā)訪問(wèn)的。所以對(duì)象能一個(gè)一個(gè)接連不斷的傳過(guò)來(lái),有很多人在運(yùn)行的時(shí)候會(huì)碰到EOFException, 然后百思不得其解,去各種論壇問(wèn)解決方案。其實(shí)筆者這里想說(shuō),這個(gè)異常不是必須聲明的,也就是說(shuō)它雖然是異常,但其實(shí)是正常運(yùn)行結(jié)束的標(biāo)志。EOF表示讀到了文件尾,發(fā)送結(jié)束自然連接也就斷開(kāi)了。如果這影響到了你程序的正確性的話,請(qǐng)各位靜下心來(lái)看看自己程序的業(yè)務(wù)邏輯,而不要把注意力狹隘的聚集在發(fā)送和接受的方法上。因?yàn)楣P者也被這樣的bug困擾了1整天,被很多論壇的帖子誤解了很多次最后得出的教訓(xùn)。如果在while循環(huán)中去readObject,本質(zhì)上是沒(méi)有問(wèn)題的,有對(duì)象數(shù)據(jù)來(lái)就會(huì)讀,沒(méi)有就自動(dòng)阻塞。那么拋出EOFException一定是因?yàn)檫B接斷了還在繼續(xù)read,什么原因?qū)е逻B接斷了呢?一定是業(yè)務(wù)邏輯哪里存在錯(cuò)誤,比如NullPoint、 ClassCaseException、ArrayOutofBound,即使程序較大也沒(méi)關(guān)系,最多只要單步調(diào)適一次就能很快發(fā)現(xiàn)bug并且解決它。