單例模式及相關(guān)的空指針的思考

單例模式的討論珠玉在前,我就不過多敘述基礎(chǔ)的內(nèi)容敲茄。感興趣的朋友可以閱讀參考資料1位谋。


假設(shè)現(xiàn)在有一種變形的餓漢式單例山析,單例的賦值是在類的構(gòu)造函數(shù)里面進(jìn)行的堰燎。樣例代碼如下:

public class SingletonSample{
    private static SingletonSample mInstance;
    private SingletonSample(String arg){
        mInstance = this;
    }
    public static SingletonSample getInstance(){
        return mInstance;
    }
    public void doSomething(){
        //做一些事情
        ...
    }
}

那么上文的getInstance函數(shù)是不能保證返回值非空的。那在程序中就有可能出現(xiàn)空指針笋轨,進(jìn)而導(dǎo)致崩潰秆剪。
限制單例的賦值不能變換位置的話,現(xiàn)在有兩種解決方案擺在我們面前:

  1. getInstance方法不保證非空爵政,在外部任一調(diào)用getInstance函數(shù)的地方先進(jìn)行非空判定再執(zhí)行相關(guān)方法仅讽。
  2. getInstance方法保證非空

顯然方案一是不需要更多思考的钾挟,直接就是空指針情形的常見解決方案洁灵,判空,非空則執(zhí)行邏輯掺出,否則不執(zhí)行徽千。但這種解決方案我覺得不好,既要修改已有的很多個(gè)調(diào)用處汤锨,即多個(gè)文件双抽,還要保證之后調(diào)用的地方都自覺加上非空判定。
所以我選擇方案二闲礼。但是根據(jù)限制條件“單例的賦值不能變換位置”牍汹,自然是不能把當(dāng)前這個(gè)單例轉(zhuǎn)為標(biāo)準(zhǔn)的餓漢式或懶漢式铐维。既然不能隨意改動(dòng)到mInstance的值,那有沒有別的方法達(dá)成getInstance方法保證非空的目的呢慎菲?
哈哈哈哈嫁蛇,當(dāng)然有啦,mInstance為null的時(shí)候返回一個(gè)空的占位符實(shí)例不就行了嗎露该。
修改后的樣例代碼如下:

public class SingletonSample{
    private static SingletonSample mInstance;
    private static final SingletonSample PLACEHOLDER = new SingletonSample() ;
    private SingletonSample(){
        //空的構(gòu)造函數(shù)棠众,純粹為了占位符而生
    }
    private SingletonSample(String arg){
        mInstance = this;
    }
    public static SingletonSample getInstance(){
        if (mInstance == null) {
            return PLACEHOLDER;
        }
        return mInstance;
    }
    public void doSomething(){
        if(!isValidInstance()){
            return;
        }
        //做一些事情
        ...
    }
    private boolean isValidInstance(){
        return this != PLACEHOLDER;
    }
}

這其實(shí)也是空指針情形的一種常見解決方案,空的時(shí)候返回一個(gè)默認(rèn)值/占位符有决,不空的時(shí)候返回實(shí)際值闸拿。

可以看到還加了個(gè)isValidInstance的判斷函數(shù),原因是實(shí)際邏輯操作的時(shí)候书幕,可能占位符/默認(rèn)值并不能執(zhí)行新荤,所以要在所有的對(duì)外方法中添加實(shí)例檢查。

這樣修改后台汇,其實(shí)還是不可避免地要進(jìn)行多處修改苛骨,但這次的多處修改都是在當(dāng)前單例類里面的苟呐,不會(huì)涉及外部類痒芝;同時(shí)也是要保證之后當(dāng)前單例類里新增的對(duì)外實(shí)例方法,都要進(jìn)行實(shí)例驗(yàn)證才能進(jìn)行邏輯操作牵素,但是這仍舊是當(dāng)前類里的修改严衬,不涉及外部類。

這個(gè)解決方案在我看來笆呆,雖然還有類似的限制(要改動(dòng)多處请琳,對(duì)之后的邏輯有要求),但是還是比第一種解決方案要優(yōu)秀赠幕,因?yàn)橥獠空{(diào)用處有可能不是同一個(gè)開發(fā)者書寫的邏輯俄精;但把限制都約束在了同一個(gè)類里,既避免了空指針發(fā)散榕堰,也在很多情況下是同一個(gè)開發(fā)者維護(hù)的邏輯竖慧,更能避免后續(xù)Bug的產(chǎn)生。

看回PLACEHOLDER這個(gè)靜態(tài)變量逆屡,它會(huì)不會(huì)有可能為null呢圾旨?

不會(huì)。

這個(gè)變量的賦值是在類初始化的時(shí)候康二,這個(gè)值為null的話碳胳,只有可能是相關(guān)的ClassLoader都被銷毀了,否則只要這個(gè)類有加載到ClassLoader中初始化沫勿,這個(gè)變量就都不會(huì)為null挨约。詳細(xì)參見參考資料2味混。


參考資料

  1. 單例這種設(shè)計(jì)模式 - 技術(shù)小黑屋
  2. Are static fields open for garbage collection? - Stack Overflow
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市诫惭,隨后出現(xiàn)的幾起案子翁锡,更是在濱河造成了極大的恐慌,老刑警劉巖夕土,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馆衔,死亡現(xiàn)場離奇詭異,居然都是意外死亡怨绣,警方通過查閱死者的電腦和手機(jī)角溃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來篮撑,“玉大人减细,你說我怎么就攤上這事∮浚” “怎么了未蝌?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茧妒。 經(jīng)常有香客問我萧吠,道長,這世上最難降的妖魔是什么桐筏? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任纸型,我火速辦了婚禮,結(jié)果婚禮上九昧,老公的妹妹穿的比我還像新娘绊袋。我一直安慰自己,他們只是感情好铸鹰,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著皂岔,像睡著了一般蹋笼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上躁垛,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天剖毯,我揣著相機(jī)與錄音,去河邊找鬼教馆。 笑死逊谋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的土铺。 我是一名探鬼主播胶滋,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼板鬓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了究恤?” 一聲冷哼從身側(cè)響起俭令,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎部宿,沒想到半個(gè)月后抄腔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡理张,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年赫蛇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雾叭。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡棍掐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拷况,到底是詐尸還是另有隱情作煌,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布赚瘦,位于F島的核電站粟誓,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏起意。R本人自食惡果不足惜鹰服,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望揽咕。 院中可真熱鬧悲酷,春花似錦、人聲如沸亲善。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蛹头。三九已至顿肺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渣蜗,已是汗流浹背屠尊。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留耕拷,地道東北人讼昆。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像骚烧,于是被迫代替她去往敵國和親浸赫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子闰围,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 單例模式(SingletonPattern)一般被認(rèn)為是最簡單、最易理解的設(shè)計(jì)模式掺炭,也因?yàn)樗暮啙嵰锥枳纾琼?xiàng)目中最...
    成熱了閱讀 4,255評(píng)論 4 34
  • 前言 本文主要參考 那些年,我們一起寫過的“單例模式”涧狮。 何為單例模式炕矮? 顧名思義,單例模式就是保證一個(gè)類僅有一個(gè)...
    tandeneck閱讀 2,517評(píng)論 1 8
  • 1.單例模式概述 (1)引言 單例模式是應(yīng)用最廣的模式之一者冤,也是23種設(shè)計(jì)模式中最基本的一個(gè)肤视。本文旨在總結(jié)通過Ja...
    曹豐斌閱讀 2,941評(píng)論 6 47
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法涉枫,內(nèi)部類的語法邢滑,繼承相關(guān)的語法,異常的語法愿汰,線程的語...
    子非魚_t_閱讀 31,664評(píng)論 18 399
  • 你說帥重不重要困后? 廢話,當(dāng)然重要了衬廷。摇予。。 想想小鮮肉就知道了吗跋,侧戴,, 要知道跌宛,出去個(gè)別有天賦的酗宋,很多人都說后天學(xué)習(xí)的...
    段子手萬千閱讀 185評(píng)論 0 0