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