阿里巴巴Java編程規范考試
今天在阿里雲官網把阿里巴巴Java編程規范認證考試考過了, 寫下這篇文章總結一下考試中需要注意的知識點, 主體內容還是要直接看規范:
- 編程規約
- 異常日志
- 單元測試
- 安全規約
- MySQL數據庫
- 工程結構
編程規約
- 類名使用UpperCamelCase風格, 但以下情形例外: DO / BO / DTO / VO / AO / PO 等, 如UserDO等。在阿里巴巴Java編程規范中POJO(Plain Ordinary Java Object)專指只有setter / getter / toString 的簡單類, 包括DO / BO / DTO / VO 等, 禁止命名成xxxPOJO。
- 定義DO / DTO / VO 等POJO類時, 不要設定任何屬性默認值。
- 定義數組: 類型與中括號緊挨相連來定義, 如int[] arrayDemo, 不能使用“String args[]”這種方式。
- 包名統一使用小寫, 單數形式; 類名如果有復數含義,可以使用復數形式;例如:包名com.alibaba.ai.util, l類名MessageUtils。
- 任何二目、三目運算符的左右兩邊都需要加一個空格, 注意一目運算++ 是不需要加空格的。
- 單行字符數限制不超過120個, 單個方法的總行數不超過80行。
- 序列化類新增屬性時, 請不要修改serialVersionUID字段, 避免反序列化失敗; 如果完全不兼容升級, 避免反序列化混亂, 那么請修改serialVersionUID值。
- 慎用Object的clone方法/BeanUtil的copy方法來拷貝對象, 若想實現深拷貝需要重寫clone方法實現屬性對象的拷貝。
- ArrayList的subList的類型是java.util.RandomAccessSubList, 是ArrayList的一個視圖, 不能強轉成ArrayList; 對於SubList子列表的所有操作最終會反映到原列表上; 對原列表的修改, 會導致子列表的遍歷、增加、刪除均會產生ConcurrentModificationException異常; 同時, subList沒有實現Serializable接口, 若RPC接口的List類型參數接受了SubList類型的實參,則在RPC調用時會報出序列化異常。比如我們常用的guava中的Lists.partition,切分后的子list實際都是SubList類型,在傳給RPC接口之前,需要用new ArrayList()包一層,否則會報序列化異常。
- 使用集合轉數組的方法, 必須使用集合的toArray(T[] array), 傳入的是類型完全一樣的數組, 大小就是list.size()。
- 方法內部, 拋出異常實例對象為throw; 方法簽名中, 拋給調用者的關鍵字為throws。
- 注意checked/unchecked異常, 見下圖Java 異常類層次結構, unchecked異常包括Error、RuntimeException, checked異常必須被顯式地捕獲或者傳遞。

- Hashtable/ConcurrentHashMap的K/V都不允許為null, HashMap的K/V都允許為null, TreeMap的K不允許為null、V允許為null。
- FixedThreadPool和SingleThreadPool允許的請求隊列長度為Integer.MAX.VALUE, 可能會堆積大量的請求, 從而導致OOM; CachedThreadPool和ScheduledThreadPool允許的創建線程數量為Integer.MAX.VALUE, 可能會創建大量的線程, 從而導致OOM。
- 不要在視圖模板中(vm)中加入變量聲明, 邏輯運算符, 更不要在vm中加入任何復雜的邏輯, 視圖的職責是展示, 不要搶模型和控制器的活。
異常日志
- 應用中不可直接使用日志系統(Log4j、Logback)中的API, 而應使用門面模式的日志框架(SLF4J、JCL)。
- 對trace/debug/info級別的日志輸出, 必須使用條件輸出形式或者使用占位符的方式。
單元測試
- 好的單元測試必須遵守AIR原則: A->Automatic(自動化), I->Independent(獨立性), R->Repeatable(可重復)。
- 編寫單元測試代碼遵守BCDE原則, 以保證被測試模塊的交付質量: B->Border 邊界測試; C->Correct 正確的輸入, 預期的結果; D->Design 與設計文檔相結合, 來編寫單元測試; E->Error 強制錯誤信息輸入, 預期的結果。
- 語句覆蓋是最弱的一種度量方式; 即使是路徑覆蓋也不能保證程序完全沒問題; 條件覆蓋率!=分支覆蓋率; 條件覆蓋, if里面的每個判斷條件, 如if(A && B), 當A/B為true/false、false/true時該語句的條件覆蓋率100%; 分支覆蓋, if邏輯/沒走if邏輯, 當A/B為true/true、false/true時分支覆蓋率100%。
安全規約
- 水平權限漏洞一般出現在一個用戶對象關聯多個其他對象(訂單、地址等)、並且要實現對關聯對象的CRUD的時候。開發容易習慣性的在生成CRUD表單(或AJAX請求)的時候根據認證過的用戶身份來找出其有權限的被操作對象id,提供入口,然后讓用戶提交請求,並根據這個id來操作相關對象。在處理CRUD請求時,往往默認只有有權限的用戶才能得到入口,進而才能操作相關對象,因此就不再校驗權限了。可悲劇的是大多數對象的ID都被設置為自增整型,所以攻擊者只要對相關id加1、減1、直至遍歷,就可以操作其他用戶所關聯的對象了。
- Web應用必須正確配置 Robots文件,非 SEO URL必須配置為禁止爬蟲訪問。SEO-Search Engine Optimization。
MySQL數據庫
- 如果存儲的字符串長度幾乎相等, 使用char定長字符串類型
- varchar是可變長字符串, 長度不要超過5000, 如果存儲長度大於此值, 定義字段類型為text, 獨立出來一張表, 用主鍵來對應。
- 字段允許適當冗余, 以提高查詢性能, 但必須考慮數據一致。冗余字段應遵循:不是頻繁修改的字段、不是varchar超長字段、更不能是text字段。
- 表的命名最好是加上“業務名稱_表的作用”。
- 表必備三字段:id, gmt_create, gmt_modified。
- 需要join的字段, 數據類型必須絕對一致; 多表關聯查詢時, 保證被關聯的字段需要有索引; 超過三個表禁止join。
- varchar字段上建立索引時, 必須指定索引長度。
- 頁面搜索嚴禁左模糊或者全模糊, 如果需要請走搜索引擎來解決。
- 索引中有范圍查找, 那么索引有序性無法利用, 如: WHERE a > 10 ORDER BY b, WHERE a IN(1, 2, 3) ORDER BY b, 則索引a_b無法排序; 如果在WHERE和ORDER BY的欄位上應用表達式(函數)時,則無法利用索引來實現order by的優化。
- WHERE條件列可以不按照索引定義的順序出現,只要出現的索引列在索引定義順序的列上能連起來就行,但是order by列不同,出現順序一定得按照索引定義的順序,否則無法使用索引進行排序; order by子句和查找型查詢的限制是一樣的,需要滿足索引的最左前綴的要求,否則mysql都需要執行排序操作,而無法使用索引排序。
- 建組合索引的時候, 區分度最高的在最左邊, 如WHERE a=? and b=?, 當a列值幾乎接近於唯一 , 那么只需要單建idx_a索引即可; 建索引時, 請把等號條件的列前置, 如WHERE a>? and b=? 那么即使a的區分度更高, 也必須把b放在索引的最前列。
- MySQL涉及的索引從數據結構角度來看涉及到B-Tree、Hash、R-Tree、Full-text, 從物理存儲角度, 聚集索引(clustered)、非聚集索引(non-clustered); 聚簇索引(Clustered Indexes),主鍵就是聚集索引。
- 聚簇索引保證關鍵字的值相近的元組存儲的物理位置也相同(所以字符串類型不宜建立聚簇索引,特別是隨機字符串,會使得系統進行大量的移動操作),且一個表只能有一個聚簇索引。
- MySQL中, InnoDB引擎表是(聚集)索引組織表, 而MylSAM引擎表則是堆組織表。
- 二級索引又稱輔助索引、非聚集索引(no-clustered index)。然而二級索引的葉子節點不保存記錄中的所有列,其葉子節點保存的是<健值,(記錄)地址>。好似聚集索引中非葉子節點保存的信息(葉子節點保存的數據本身),不同的是二級索引保存的是記錄地址,而聚集索引保存的是下一層節點地址。
- 當一列的值全是NULL時, count(col)的返回結果為0, 但sum(col)的返回結果為NULL, 因此使用sum()時需要注意NPE問題。
- NULL與任何值的直接比較都為NULL。
- iBATIS自帶的queryForList(String statementName, int start, int size)不推薦使用, 其實現方式是在數據庫取到statementName對應的SQL語句的所有記錄, 再通過subList取start, size的集合。
工程結構
- GAV: GroupID->com.{公司/BU}.業務線.[子業務線], 最多4級; ArtifactID->產品線名-模塊名; Version->主版本號.次版本號.修訂號。
- 線上應用不要依賴SNAPSHOT版本(安全包除外)。不依賴SNAPSHOT版本是保證應用發布的冪等性, 另外, 也可以加快編譯時的打包構建。
- dependency:resolve 打印出已解決依賴列表, dependency:tree 打印層級依賴關系, 可以用excludes排除jar包。
- 二方庫里可以定義枚舉類型, 參數可以使用枚舉類型, 但是接口返回值不允許使用枚舉類型或者包含枚舉類型的POJO對象, 會有反序列化的問題。
如果本文檔有什么錯誤, 歡迎大家指出。
原文地址:https://blog.csdn.net/maomaotracy/article/details/80786610