国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

[Effective Java]第十一章 序列化

2019-11-14 22:45:54
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
[Effective java]第十一章 序列化聲明:原創(chuàng)作品,轉(zhuǎn)載時(shí)請(qǐng)注明文章來(lái)自SAP師太技術(shù)博客( 博/客/園www.cnblogs.com):m.survivalescaperooms.com/jiangzhengjun,并以超鏈接形式標(biāo)明文章原始出處,否則將追究法律責(zé)任!原文鏈接:http://m.survivalescaperooms.com/jiangzhengjun/p/4255724.html 第十一章 序列化 74、 謹(jǐn)慎地實(shí)現(xiàn)Serializable接口

實(shí)現(xiàn)Serializable接口而付出的最大代價(jià)是,一旦一個(gè)類被發(fā)布,就大降低了“改變這個(gè)類的實(shí)現(xiàn)”的靈活性。如采用默認(rèn)的序列化方式時(shí)(僅實(shí)現(xiàn)Serializable),且沒(méi)有在一個(gè)名為serialVersionUID的私有靜態(tài)final的long域顯示地指定該標(biāo)識(shí)號(hào),則如果類改變了,則會(huì)導(dǎo)致不兼容。

實(shí)現(xiàn)Serializable的第二個(gè)代價(jià)是,它增加了出現(xiàn)Bug和安全漏洞的可能性。反序列化過(guò)程不是調(diào)用原有的構(gòu)造器,所以你很容易忘記要確保:反序列化過(guò)程必須也要保證所有“由真正的構(gòu)造器建立起來(lái)約束關(guān)系”,并且不允許攻擊者訪問(wèn)正在構(gòu)造過(guò)程上的對(duì)象的內(nèi)部信息,依靠默認(rèn)的反序列化機(jī)制,很容易對(duì)象的約束關(guān)系遭到破壞,以及遭受非法訪問(wèn)(第76條)。

實(shí)現(xiàn)Serializable的第三個(gè)代價(jià)是,隨著類發(fā)行新的版本,相關(guān)的測(cè)試負(fù)擔(dān)也增加了。

實(shí)現(xiàn)Serializable接口并不是一個(gè)很輕松就可以做出的決定。根據(jù)經(jīng)驗(yàn),如Data和BigInteger這樣的的值類應(yīng)該實(shí)現(xiàn)Serializable,大多數(shù)的集合類也是應(yīng)該如此。代表活動(dòng)實(shí)體的類,如線程池,一般不應(yīng)該實(shí)現(xiàn)Serializable。

為了繼承而設(shè)計(jì)的類,應(yīng)該盡可能少地去實(shí)現(xiàn)Serializable接口,用戶的接口也應(yīng)該盡可能少地繼承Serializable接口。如果違反了這條規(guī)則,擴(kuò)展這個(gè)類或者實(shí)現(xiàn)這個(gè)接口的程序員就會(huì)背上沉重的負(fù)擔(dān)。然后在有些情況下是合適的,如,這個(gè)類或接口主要是為了參與到某個(gè)框架中,而該框架要求所有參與者都實(shí)現(xiàn)Serializable接口,則實(shí)現(xiàn)Serializable是有意義的。

對(duì)于為繼承而設(shè)計(jì)的不可序列化的類,你應(yīng)該考慮提供一個(gè)無(wú)參構(gòu)造器,因?yàn)樗淖宇惪赡苁强尚蛄谢模坏┳宇悓?shí)現(xiàn)Serializable接口,則在反序列化時(shí)會(huì)調(diào)用調(diào)用父類的無(wú)參構(gòu)造器。最好在所有約束關(guān)系都已經(jīng)建立的情況下再創(chuàng)建對(duì)象。下面是一個(gè)父類不可序列化,而子類可序列化的建議做法:

//不可序列化

publicabstractclassAbstractFoo {

PRivateintx,y;//狀態(tài)

//枚舉字段用于跟蹤初始化于哪種狀態(tài):NEW-新建,INITIALIZING-正在初始化,INITIALIZED-初始化完成

privateenumState{

NEW,INITIALIZING,INITIALIZED

};

/*

*初始化到哪種狀態(tài)了

*注意,init是一個(gè)原子引用。在遇到特定的情況下,確保對(duì)象的完整性是很重要的。如果沒(méi)有這樣的防范,

*萬(wàn)一有個(gè)線程要在某個(gè)實(shí)例上調(diào)用initialize,而另一個(gè)線程又要企圖使用這個(gè)實(shí)例,第二個(gè)線程就有

*可能看到這個(gè)實(shí)例處于不一致的狀態(tài)。這種模式利用compareAndSet方法來(lái)操作枚舉的大孩子引用。

*/

privatefinalAtomicReference<State>init=newAtomicReference<State>(State.NEW);

//該域是第一版中的

// private boolean initialized = false;//第一版

publicAbstractFoo(intx,inty) {

initialize(x, y);

}

//此構(gòu)造和下面的方法讓子類的readObject方法來(lái)初始化我們的狀態(tài)

protectedAbstractFoo() {//受保護(hù)的構(gòu)造器

}

protectedfinalvoidinitialize(intx,inty) {

//compareAndSet(V expect, V update):如果當(dāng)前值==預(yù)期值expect,

//則以原子方式將該值設(shè)置為給定的更新值update。如果還未初始化時(shí),將初始狀態(tài)設(shè)為:INITIALIZING

if(!init.compareAndSet(State.NEW, State.INITIALIZING))

//if (initialized)//第一版

thrownewIllegalStateException("Already initialized");

this.x= x;

this.y= y;

//構(gòu)造完后設(shè)置成完成狀態(tài)

init.set(State.INITIALIZED);

// initialized=true;//第一版

}

//這些方法提供了訪問(wèn)內(nèi)部狀態(tài),因此可以

//通過(guò)子類的writeObject方法來(lái)手動(dòng)序列化。

protectedfinalintgetX() {

checkInit();

returnx;

}

protectedfinalintgetY() {

checkInit();

returny;

}

//所有共有的與保護(hù)的實(shí)例方法都必須調(diào)用

privatevoidcheckInit() {

// if(!initialized)//第一版

if(init.get() != State.INITIALIZED)

thrownewIllegalStateException("Uninitialized");

}

//其余的略

}

//繼承不可序列化父類,但已自己實(shí)現(xiàn)Serializable接口

publicclassFooextendsAbstractFooimplementsSerializable {

privatevoidreadObject(ObjectInputStream s)throwsIOException,

ClassNotFoundException {

s.defaultReadObject();

//手工反序列化和初始化父類的狀態(tài)

intx = s.readInt();

inty = s.readInt();

initialize(x, y);

}

privatevoidwriteObject(ObjectOutputStream s)throwsIOException {

s.defaultWriteObject();

//手工序列化父類的狀態(tài)

s.writeInt(getX());

s.writeInt(getY());

}

// Constructor does not use the fancy mechanism

publicFoo(intx,inty) {

super(x, y);

}

privatestaticfinallongserialVersionUID= 1856835860954L;

}

內(nèi)部類不應(yīng)該實(shí)現(xiàn)Serializable接口,它們使用編譯器產(chǎn)生的合成域來(lái)保存指向外圍實(shí)例的引用,以保存來(lái)自外圍作用域的局部變量的值。“這些域如何對(duì)應(yīng)到類定義中”并沒(méi)有明確的規(guī)定,就好像匿名類和局部類的名稱一樣,它們都是由編譯器臨時(shí)產(chǎn)生的,我們不能引用它們。因此,內(nèi)部類默認(rèn)序列化形式是定義不清楚的。然而,靜態(tài)成員類卻可以實(shí)現(xiàn)Serializable接口。

總之,實(shí)現(xiàn)Serializable接口不是容易的事。實(shí)現(xiàn)Serializable接口是個(gè)嚴(yán)肅的承諾,必須認(rèn)真對(duì)待。如果類是為了繼承使用的,則一定要提供一個(gè)默認(rèn)構(gòu)造器,以防止子類序列化。

75、 考慮使用自定義的序列化形式

Word-spacing: 0

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 武平县| 伊金霍洛旗| 三穗县| 五大连池市| 绵阳市| 武鸣县| 浑源县| 六安市| 深圳市| 福泉市| 舟曲县| 屏东市| 察隅县| 宝山区| 江华| 中西区| 洪雅县| 太仆寺旗| 佛坪县| 福鼎市| 双城市| 波密县| 土默特左旗| 绥棱县| 綦江县| 寻甸| 高阳县| 文登市| 津市市| 荔浦县| 夹江县| 宣恩县| 苏州市| 五常市| 洪雅县| 库车县| 房产| 交口县| 西峡县| 通江县| 绥宁县|