你編寫的程式高效、優雅嗎?阿里架構師教你編寫高效優雅Java程式
面向物件
構造器引數太多怎麼辦?
用 builder 模式,用在
1、5 個或者 5 個以上的成員變數
2、引數不多,但是在未來,引數會增加
Builder 模式:
屬於物件的建立模式,一般有
- 1. 抽象建造者:一般來說是個介面,包含 1)建造方法,建造部件的方法(不止一
個),2)返回產品的方法
- 2. 具體建造者
- 3. 導演者,呼叫具體的建造者,建立產品物件
- 4. 產品,需要建造的複雜物件
對於客戶端,建立導演者和具體建造者,並把具體建造者交給導演者,然後由客戶端通知導演者操縱建造者進行產品的建立。
在實際的應用過程中,有時會省略抽象建造者和導演者。
不需要例項化的類應該構造器私有
如,一些工具類提供的都是靜態方法,這些類是不應該提供具體的例項的。可以參考 JDK
中的 Arrays。
不要建立不必要的物件
1. 避免無意中建立的物件,如自動裝箱
2. 可以在類的多個例項之間重用的成員變數,儘量使用 static。
但是,要記住,是不要建立不必要的物件,而不是不要建立物件。
物件池要謹慎使用,除非建立的物件是非常昂貴的操作,如資料庫的連線,巨型物件等
等。
避免使用終結方法
finalizer 方法,jdk 不能保證何時執行,也不能保證一定會執行。如果有確實要釋放的資源
應該用 try/finally。
使類和成員的可訪問性最小化
編寫程式和設計架構,最重要的目標之一就是模組之間的解耦。使類和成員的可訪問性最
小化無疑是有效的途徑之一。
使可變性最小化
儘量使類不可變,不可變的類比可變的類更加易於設計、實現和使用,而且更不容易出
錯,更安全。
常用的手段:
不提供任何可以修改物件狀態的方法;
使所有的域都是 final 的。
使所有的域都是私有的。
使用寫時複製機制。帶來的問題:會導致系統產生大量的物件,而且效能有一定的影響,
需要在使用過程中小心權衡。
複合優先於繼承
繼承容易破壞封裝性,而且會使子類的實現依賴於父類。
複合則是在類中增加一個私有域,引用類的一個例項,這樣的話就避免了依賴類的具體實
現。
只有在子類確實是父類的一個子型別時,才比較適合用繼承。
介面優於抽象類
java 是個單繼承的,但是類允許實現多個介面。
所以當發生業務變化時,新增介面,並且需要進行業務變化的類現新介面即可。但是抽象
類有可能導致不需要變化的類也不得不實現新增的業務方法。
在 JDK 裡常用的一種設計方法是:定義一個介面,宣告一個抽象的骨架類實現介面,骨架
類類實現通用的方法,而實際的業務類可以同時實現介面又繼承骨架類,也可以只實現接
口。
如 HashSet 實現了 implements Set 介面 但是又 extends 類 AbstractSet,而
AbstractSet 本身也實現了 Set 介面。其他如 Map,List 都是這樣的設計的。
方法
可變引數要謹慎使用
可變引數是允許傳 0 個引數的
如果是引數個數在 1~多個之間的時候,要做單獨的業務控制。
看程式碼
返回零長度的陣列或集合,不要返回 null
方法的結果返回 null,會導致呼叫方的要單獨處理為 null 的情況。返回零長度,呼叫方可
以統一處理,如使用 foreach 即可。
JDK 中也為我們提供了 Collections.EMPTY_LIST 這樣的零長度集合
優先使用標準的異常
要儘量追求程式碼的重用,同時減少類載入的數目,提高類裝載的效能。
常用的異常:
IlegalAraumentException -- 呼叫者傳遞的引數不合適
lllegalStateException – 接收的物件狀態不對,
NullPoint
UnsupportedOperationException –不支援的操作
通用程式設計
用列舉代替 int 常量
宣告的一個列舉本質就是一個類,每個具體的列舉值就是這個列舉類的例項。
列舉更多作用,看程式碼。
將區域性變數的作用域最小化
- 1. 在第一次使用的地方進行宣告
- 2. 區域性變數都是要自行初始化,初始化條件不滿足,就不要宣告
最小化的好處,減小區域性變量表的大小,提示效能;同時避免區域性變數過早宣告導致不正
確的使用。
精確計算,避免使用 float 和 double
可以使用 int 或者 l