閱讀阿里巴巴Java開發手冊,截取一些需要注意的地方

原文出自  阿里巴巴Java開發手冊,禁止用於商業用途,違者必究

【推薦】集合初始化時,指定集合初始值大小。 
說明:HashMap 使用 HashMap(int initialCapacity) 初始化, 
正例:initialCapacity = (需要存儲的元素個數 / 負載因子) + 1。注意負載因子(即loader factor)默認爲 0.75,如果暫時無法確定初始值大小,請設置爲 16(即默認值)。 

反例:HashMap 需要放置 1024 個元素,由於沒有設置容量初始大小,隨着元素不斷增加,容量 7 次被迫擴大,resize 需要重建hash 表,嚴重影響性能。    原來多次擴大Map容量會影響效率。


【強制】使用工具類 Arrays.asList()把數組轉換成集合時,不能使用其修改集合相關的方法,它的add/remove/clear 方法會拋出 UnsupportedOperationException 異常。 
說明:asList 的返回對象是一個 Arrays 內部類,並沒有實現集合的修改方法。Arrays.asList
體現的是適配器模式,只是轉換接口,後臺的數據仍是數組。 
    String[] str = new String[] { "you", "wu" }; 
    List list = Arrays.asList(str); 
第一種情況:list.add("yangguanbao"); 運行時異常。 

第二種情況:str[0] = "gujin"; 那麼 list.get(0)也會隨之修改。


【推薦】循環體內,字符串的連接方式,使用 StringBuilder 的 append 方法進行擴展。 
說明:反編譯出的字節碼文件顯示
每次循環都會 new 出一個 StringBuilder 對象,然後進行append 操作,最後通過 toString 方法返回String 對象,造成內存資源浪費。 
反例: 
String str = "start";      
    for (int i = 0; i < 100; i++) {          
str = str + "hello";      

}  


【推薦】 類內方法定義順序依次是:公有方法或保護方法 > 私有方法 > getter/setter方法。 

說明:公有方法是類的調用者和維護者最關心的方法,首屏展示最好;保護方法雖然只是子類關心,也可能是“模板設計模式”下的核心方法;而私有方法外部一般不需要特別關心,是一個黑盒實現;因爲承載的信息價值較低,所有 Service 和DAO的getter/setter 方法放在類體最後。

學習一個新名詞,黑盒實現


關於基本數據類型與包裝數據類型的使用標準如下: 
 1) 【強制】所有的 POJO 類屬性必須使用包裝數據類型。 
 2) 【強制】RPC 方法的返回值和參數必須使用包裝數據類型。 
 3) 【推薦】所有的局部變量使用基本數據類型。 
 說明:POJO 類屬性沒有初值是提醒使用者在需要使用時,必須自己顯式地進行賦值,任何NPE 問題,或者入庫檢查,都由使用者來保證。 
 正例:數據庫的查詢結果可能是 null,因爲自動拆箱,用基本數據類型接收有 NPE 風險。 

 反例:比如顯示成交總額漲跌情況,即正負 x%,x 爲基本數據類型,調用的 RPC 服務,調用不成功時,返回的是默認值,頁面顯示爲0%,這是不合理的,應該顯示成中劃線。所以包裝數據類型的null 值,能夠表示額外的信息,如:遠程調用失敗,異常退出。 


【參考】各層命名規約:  
A) Service/DAO 層方法命名規約 
 1) 獲取單個對象的方法用 get 做前綴。 
 2) 獲取多個對象的方法用 list 做前綴。 
 3) 獲取統計值的方法用 count 做前綴。 
 4) 插入的方法用 save/insert 做前綴。 
 5) 刪除的方法用 remove/delete 做前綴。 
 6) 修改的方法用 update 做前綴。 
B) 領域模型命名規約 
 1) 數據對象:xxxDO,xxx 即爲數據表名。 
 2) 數據傳輸對象:xxxDTO,xxx 爲業務領域相關的名稱。 
 3) 展示對象:xxxVO,xxx 一般爲網頁名稱。 

 4) POJO 是 DO/DTO/BO/VO 的統稱,禁止命名成 xxxPOJO。


【推薦】使用entrySet 遍歷Map 類集合KV,而不是keySet 方式進行遍歷。 
說明:keySet 其實是遍歷了 2次,一次是轉爲 Iterator 對象,另一次是從 hashMap 中取出key 所對應的 value。而 entrySet 只是遍歷了一次就把 key 和value 都放到了entry 中,效率更高。如果是JDK8,使用Map.foreach方法。 

正例:values()返回的是 V 值集合,是一個list 集合對象;keySet()返回的是K 值集合,是一個Set 集合對象;entrySet()返回的是K-V 值組合集合。 

                Map<String,String> testMap = new HashMap<String, String>();
		
		Iterator<Entry<String, String>> iterator = testMap.entrySet().iterator();
		
		while(iterator.hasNext()){
			Entry<String, String> next = iterator.next();
			String key = next.getKey();
			String value = next.getValue();
		}


【參考】合理利用好集合的有序性(sort)和穩定性(order),避免集合的無序性(unsort)和不穩定性(unorder)帶來的負面影響。 

說明:有序性是指遍歷的結果是按某種比較規則依次排列的。穩定性指集合每次遍歷的元素次序是一定的。如:ArrayList 是 order/unsort;HashMap 是unorder/unsort;TreeSet 是order/sort。


【強制】線程資源必須通過線程池提供,不允許在應用中自行顯式創建線程。 

說明:使用線程池的好處是減少在創建和銷燬線程上所花的時間以及系統資源的開銷,解決資源不足的問題。如果不使用線程池,有可能造成系統創建大量同類線程而導致消耗完內存或者“過度切換”的問題。


【強制】線程池不允許使用 Executors 去創建,而是通過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學更加明確線程池的運行規則,規避資源耗盡的風險。 
說明:Executors 返回的線程池對象的弊端如下: 
1)FixedThreadPool和 SingleThreadPool: 
 允許的請求隊列長度爲 Integer.MAX_VALUE,可能會堆積大量的請求,從而導致 OOM。 
2)CachedThreadPool和 ScheduledThreadPool: 
 允許的創建線程數量爲 Integer.MAX_VALUE,可能會創建大量的線程,從而導致 OOM。


【強制】高併發時,同步調用應該去考量鎖的性能損耗。能用無鎖數據結構,就不要用鎖;能鎖區塊,就不要鎖整個方法體;能用對象鎖,就不要用類鎖。 

說明:儘可能使加鎖的代碼塊工作量儘可能的小,避免在鎖代碼塊中調用 RPC 方法。 


【參考】下列情形,需要進行參數校驗: 
 1) 調用頻次低的方法。 
 2) 執行時間開銷很大的方法。此情形中,參數校驗時間幾乎可以忽略不計,但如果因爲參數錯誤導致中間執行回退,或者錯誤,那得不償失。 
 3) 需要極高穩定性和可用性的方法。 
 4) 對外提供的開放接口,不管是 RPC/API/HTTP 接口。 

 5) 敏感權限入口。


【強制】注意 Math.random() 這個方法返回是 double 類型,注意取值的範圍 0≤x<1(能夠取到零值,注意除零異常),如果想獲取整數類型的隨機數,不要將 x 放大10的若干倍然後取整,直接使用Random 對象的 nextInt 或者nextLong 方法。 


【強制】對大段代碼進行 try-catch,這是不負責任的表現。catch時請分清穩定代碼和非穩定代碼,穩定代碼指的是無論如何不會出錯的代碼。對於非穩定代碼的 catch 儘可能進行區分異常類型,再做對應的異常處理。


【強制】捕獲異常是爲了處理它,不要捕獲了卻什麼都不處理而拋棄之,如果不想處理它,請將該異常拋給它的調用者。最外層的業務使用者,必須處理異常,將其轉化爲用戶可以理解的內容。


【參考】在代碼中使用“拋異常”還是“返回錯誤碼”,對於公司外的 http/api 開放接口必須使用“錯誤碼”而應用內部推薦異常拋出;跨應用間RPC 調用優先考慮使用Result 方式,封裝 isSuccess()方法、“錯誤碼”、“錯誤簡短信息”。 
說明:關於RPC 方法返回方式使用 Result 方式的理由: 
 1)使用拋異常返回方式,調用方如果沒有捕獲到就會產生運行時錯誤。 

 2)如果不加棧信息,只是 new 自定義異常,加入自己的理解的 error message,對於調用端解決問題的幫助不會太多。如果加了棧信息,在頻繁調用出錯的情況下,數據序列化和傳輸的性能損耗也是問題。 


【強制】表名、字段名必須使用小寫字母或數字,禁止出現數字開頭,禁止兩個下劃線中間只出現數字。數據庫字段名的修改代價很大,因爲無法進行預發佈,所以字段名稱需要慎重考慮。 
說明:MySQL 在Windows 下不區分大小寫,但在 Linux 下默認是區分大小寫。因此,數據庫名、表名、字段名,都不允許出現任何大寫字母,避免節外生枝。 
正例:aliyun_admin,rdc_config,level3_name 

反例:AliyunAdmin,rdcConfig,level_3_name 


【推薦】字段允許適當冗餘,以提高查詢性能,但必須考慮數據一致。冗餘字段應遵循: 
 1)不是頻繁修改的字段。 
 2)不是 varchar 超長字段,更不能是 text字段。 
正例:商品類目名稱使用頻率高,字段長度短,名稱基本一成不變,可在相關聯的表中冗餘存儲類目名稱,避免關聯查詢。

發佈了25 篇原創文章 · 獲贊 14 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章