作為Java開發(fā)人員,我們會(huì)使用一些習(xí)慣用法,典型的例子,如:返回null值、濫用getter和setter,即使在沒有必要的情況下也是如此。雖然在某些情況下,這些用法可能是適當(dāng)?shù)?,但通常是?xí)慣使然,或者是我們?yōu)榱俗屜到y(tǒng)正常工作的權(quán)宜之計(jì)。在本文中,我們將討論在Java初學(xué)者甚至高級開發(fā)人員中都常見的三種情況,并探究它們是如何給我們帶來麻煩的。應(yīng)該指出的是,文中總結(jié)的規(guī)則并不是無論何時(shí)都應(yīng)該始終遵守的硬性要求。有時(shí)候,可能有一個(gè)很好的理由來使用這些模式解決問題,但是總的來說,還是應(yīng)該相對的減少這些用法。首先,我們將從Null這個(gè)關(guān)鍵字開始討論,它也是Java中使用最頻繁、但也是比較具有兩面性的關(guān)鍵字之一。
1.Returning Null(返回Null)
null一直是開發(fā)者較好的朋友,也是位于前列的敵人,這在Java中也不例外。在高性能應(yīng)用中,使用null是一種減少對象數(shù)量的可靠方法,它表明方法沒有要返回的值。與拋出異常不同,如果要通知客戶端不能獲取任何值,使用null是一種快速且低開銷的方法,它不需要捕獲整個(gè)堆棧跟蹤。
在高性能系統(tǒng)的環(huán)境之外,null的存在會(huì)導(dǎo)致創(chuàng)建更繁瑣的null返回值檢查,從而破壞應(yīng)用程序,并在解引用空對象時(shí)導(dǎo)致NullPointerExceptions。在大多數(shù)應(yīng)用程序中,返回null有三個(gè)主要原因:
表示列表中找不到元素;
表示即使沒有發(fā)生錯(cuò)誤,也找不到有效值;
表示特殊情況下的返回值。
除非有任何性能方面的原因,否則以上每一種情況都有更好的解決方案,它們不使用null,并且強(qiáng)制開發(fā)人員處理出現(xiàn)null的情況。更重要的是,這些方法的客戶端不會(huì)為該方法是否會(huì)在某些邊緣情況下返回null而傷腦筋。
2.Defaulting to Functional Programming(默認(rèn)使用函數(shù)式編程)
自從在JDK8中引入了stream和lambda表達(dá)式之后,就出現(xiàn)了向函數(shù)式編程遷移的趨勢,這理當(dāng)如此。在lambda表達(dá)式和stream出現(xiàn)之前,執(zhí)行函數(shù)式任務(wù)是非常麻煩的,并且會(huì)導(dǎo)致代碼可讀性的嚴(yán)重下降。
3.Creating Indiscriminate Gettersand Setters(濫用getter和setter)
新手程序員學(xué)到的一件事是將與類相關(guān)的數(shù)據(jù)封裝在私有字段中,并通過公共方法暴露它們。在實(shí)際使用時(shí),通過創(chuàng)建getter來訪問類的私有數(shù)據(jù),創(chuàng)建setter來修改類的私有數(shù)據(jù)。
雖然這對于新程序員來說是一個(gè)很好的學(xué)習(xí)實(shí)踐,但這種做法不能未經(jīng)思索就應(yīng)用在中級或高級編程。在實(shí)際中通常發(fā)生的情況是,每個(gè)私有字段都有一對getter和setter將類的內(nèi)部內(nèi)容暴露給外部實(shí)體。這會(huì)導(dǎo)致一些嚴(yán)重的問題,特別是在私有字段是可變的情況下。這不僅是setter的問題,甚至在只有g(shù)etter時(shí)也是如此。
我們創(chuàng)建的許多應(yīng)用程序最終都能正常工作,但是在大量應(yīng)用程序中,我們無意引入的一些問題可能只會(huì)在最極端的情況下出現(xiàn)。在某些情況下,我們做事情是出于方便,甚至是出于習(xí)慣,而很少注意這些習(xí)慣在我們使用的場景中是否實(shí)用(或安全)。