命名:
1. 為包、類、方法、變量取一個好名字,使代碼易於理解
2. 禁止使用魔鬼數字
3. 常量命名,由全大寫單詞組成,單詞間用下划線分隔,且使用 static final修飾
4. 變量、屬性命名,使用名詞,並采用首字母小寫的駝峰命名法
5. 方法的命名,用動詞和動賓結構,並采用首字母小寫的駝峰命名法
6. 類和接口的命名,采用首字母大寫的駝峰命名法
7. 包的命名,由一個或若干個單詞組成,所有的字母均為小寫
8. 數組聲明的時候使用 int[] index,而不要使用 int index[]
注釋:
1. 盡量用代碼來解釋自己
2. 注釋應解釋代碼的意圖,而不是描述代碼怎么做的
3. 保證注釋與代碼一致,避免產生誤導
4. 注釋應與其描述代碼位置相鄰,放在所注釋代碼上方或右方,並與代碼采用同樣縮進
5. 不要用注釋保留廢棄代碼
6. 不要用注釋記錄修改日志
7. 一般單行注釋用//,塊注釋用,JavaDoc注釋用
排版:
1. 團隊應遵守一致的排版風格
2. 將排版風格固化到IDE的代碼格式化配置文件中,並讓整個團隊使用
3. 在不同的概念之間,增加空行
4. 將邏輯緊密相關的代碼放在一起
5. 控制一行的寬度,不要超過120個字符
6. 在不同的概念間(關鍵字、變量、操作符等)增加空格,以便清楚區分概念
7. 采用縮進來區分不同層次的概念
8. 將局部變量的作用域最小化
9. 給if、for、do、while、switch等語句的執行體加大括號{}
10. 控制文件的長度,最好不要超過500行
變量和類型:
1. 謹慎使用靜態成員變量
2. 避免隨意進行類型強制轉換,應改善設計,或在轉換前用instanceof進行判斷3
3. 需要精確計算時不要使用float和double
4. 不能用浮點數作為循環變量
5. 浮點型數據判斷相等不能直接使用==
6. 避免同一個局部變量在前后表達不同的含義
7. 不要在單個的表達式中對相同的變量賦值超過一次
8. 基本類型優於包裝類型,注意合理使用包裝類型
方法:
1. 方法設計的第一原則是要短小
2. 方法設計應遵循單一職責原則(SRP),一個方法僅完成一個功能
3. 方法設計應遵循單一抽象層次原則(SLAP)
4. 方法設計應遵循命令與查詢職責分離原則(CQRS)
5. 不要把方法的入參當做工作變量/臨時變量,除非特別需要
6. 使用類名調用靜態方法,而不要使用實例或表達式來調用
7. 應明確規定對接口方法參數的合法性檢查由調用者負責還是由接口方法本身負責
8. 方法的參數個數不宜過多
9. 謹慎使用可變數量參數的方法
包、類和接口:
1. 類和接口的設計應遵循面向對象SOLID設計原則
2. 類的設計應遵循迪米特法則
3. 類的設計應遵循“Tell,Don't ask”原則
4. 類設計時優選組合而不是繼承
5. 除提供給外部使用的全局常量外,應盡量避免類成員變量被外部直接訪問
6. 避免在無關的變量或無關的概念之間重用名字,避免隱藏(hide)、遮蔽(shadow)和遮掩(obscure)
7. 覆寫(override)——子類與父類間
8. 重載(overload)——類內部
9. 隱藏(hide)——子類與父類間
10. 遮蔽(shadow)——類內部
11. 遮掩(obscure)——類內部
12. 不要在父類的構造方法中調用可能被子類覆寫的方法
13. 覆寫equals方法時,應同時覆寫hashCode方法
14. 子類覆寫父類方法時應加上@Override注解
15. 接口定義中去掉多余的修飾詞
16. 設計時,考慮類的可變性最小化
異常:
1. 只針對真正異常的情況才使用exception機制
2. 在拋出異常的細節信息中,應包含能捕獲失敗的信息
3. 對可恢復的情況使用受檢異常(checked exception),對編程錯誤使用運行時異常(runtime exception)
4. 不要忽略異常
5. 方法注釋和文檔中要包含所拋出異常的說明
6. 方法拋出的異常,應該與本身的抽象層次相對應
7. 對第三方API拋出大量各類異常進行封裝
8. 使用異常來做錯誤處理,而非錯誤碼
9. 在finally塊中不要使用return、break或continue使finally塊非正常結束
10. 不要直接捕獲受檢異常的基類Exception
11. 一個方法不應拋出太多類型的異常
12. 充分利用斷言
日志:
1. 日志信息准確、繁簡得當,滿足快速定位的需要
2. 日志的記錄,不要使用 System.out 與 System.err 進行控制台打印,應該使用專用的日志工具(比如:slf4j+logback)進行處理
3. 日志工具對象logger應聲明為private static final
4. 日志應分等級
5. 日志中不要記錄敏感信息
多線程並發:
1. 多線程訪問同一個可變變量,需增加同步機制
2. 禁止不加控制地創建新線程
3. 創建新線程時需指定線程名
4. 使用Thread對象的setUncaughtExceptionHandler方法注冊Runtime異常的處理者(v1.5+)
5. 不要使用Thread.stop方法,因為該方法本質是不安全的,使用它可能會導致數據遭到破壞
6. 不要依賴線程調度器、線程優先級和yield()方法
7. 采用Java1.5提供新並發工具代替wait和notify(v1.5+)
8. 使用線程安全集合在多線程間共享可變數據
9. 多線程操作同一個字符串相加,應采用StringBuffer
10. 針對線程安全性,需要進行文檔(javadoc)說明
運算和表達式:
1. 不要寫復雜的表達式
2. 運算時應避免產生溢出
3. 采用括號明確運算的優先級
控制語句:
1. 采用for-each代替傳統的for循環(v1.5+)
2. 在switch語句的每一個case、和default中都放置一條break語句
序列化:
1. 盡量不要實現Serializable接口
2. 序列化對象中的HashMap、HashSet或HashTable等集合不能包含對象自身的引用
3. 實現Serializable接口的可序列化類應該顯式聲明 serialVersionUID
泛型:
1. 在集合中使用泛型(v1.5+)
2. 類的設計可優先考慮泛型(v1.5+)
3. 方法的設計可優先考慮泛型(v1.5+)
4. 優先使用泛型集合,而不是數組(v1.5+)
其他語言特性:
1. 新代碼不要使用已標注為@deprecated的方法
2. 使用JDK自帶的API或廣泛使用的開源庫,不要自己寫類似的功能。
3. 升級到最新穩定版的Java 平台版本上,以便獲取新特性帶來的收益
4. 充分利用編譯器的告警選項
5. 使用字符串API時,應注意方法使用的是否是 “正則表達式”
6. 值類(value classes)的設計,可考慮實現Comparable接口,方便在集合中實現對象的搜索、排序、計算極值等
性能:
1. 謹慎地進行性能優化
2. 使用System.arraycopy()進行數組復制
3. 使用集合的toArray()方法將集合轉為數組(v1.42+)
4. 在Java的IO操作中,盡量使用帶緩沖的實現
資源管理:
1. 避免創建不必要的對象
2. 將對象存入HashSet,或作為key存入HashMap(或HashTable)后,必須確保該對象的hashcode值不變,避免因為hashcode值變化導致不能從集合內刪除該對象,進而引起內存泄漏的問題
3. 執行IO操作時,應該在finally里關閉IO資源
4. 消除過期的對象引用
可移植性:
1. 不要在代碼中硬編碼"\n"和"\r"作為換行符號
2. 謹慎地使用本地方法
3. 避免對第三方代碼的強依賴或陷入第三方代碼細節
國際化:
1. 在所有的輸入輸出環節,指明正確的編碼方式,進行正確的字符到字節,或字節到字符的轉換
2. 如果輸入源或輸出目標直接支持,盡可能直接使用Unicode進行輸入輸出。
3. 不要依賴平台默認的字符編碼方式。
4. 對於使用默認編碼方式的第三方代碼或者遺留代碼,可應用適配器模式,將返回的字符串轉換成Unicode內碼
5. 字符串大小寫轉換時,應加上Locale.US
參考資料及擴展閱讀材料:
1.《Java語言編程規范》
2.《核心網Java編程軍規 v1.0》
3.《Java Coding Conventions》
4.《Effective Java 第二版》
5.《代碼整潔之道》
6.《Java解惑》
7.《Java編程思想》
安全性:
1 數據校驗:
規則 1.1 校驗跨信任邊界傳遞的不可信數據
規則 1.2 禁止直接使用不可信數據來拼接SQL語句
規則 1.3 禁止直接使用不可信數據來拼接XML
規則 1.4 禁止直接使用不可信數據來記錄日志
規則 1.5 從格式化字符串中排除用戶輸入
規則 1.6 禁止向Runtime.exec() 方法傳遞不可信、未凈化的數據
規則 1.7 驗證路徑之前應該先將其標准化
規則 1.8 安全地從ZipInputStream提取文件
2 異常行為:
規則 2.1 不要抑制或者忽略已檢查異常
規則 2.2 禁止在異常中泄露敏感信息
規則 2.3 方法發生異常時要恢復到之前的對象狀態
3 I/O操作:
規則 3.1 臨時文件使用完畢應及時刪除
規則 3.2 不要將Buffer對象封裝的數據暴露給不可信代碼
規則 3.3 在多用戶系統中創建文件時指定合適的訪問許可
規則 3.4 避免讓外部進程阻塞在輸入輸出流上
規則 3.5 避免在共享目錄操作文件
4 序列化和反序列化:
規則 4.1 將敏感對象發送出信任區域前進行簽名並加密
規則 4.2 禁止序列化未加密的敏感數據
規則 4.3 防止序列化和反序列化被利用來繞過安全管理
5 平台安全:
規則 5.1 使用安全管理器來保護敏感操作
規則 5.2 防止特權區域內出現非法的數據
規則 5.3 禁止基於不信任的數據源做安全檢查
規則 5.4 禁止特權塊向非信任域泄漏敏感信息
規則 5.5 編寫自定義類加載器時應調用超類的getPermission()函數
規則 5.6 避免完全依賴URLClassLoader和java.util.jar提供的默認自動簽名認證機制
6 運行環境:
規則 6.1 禁止給僅執行非特權操作的代碼簽名
規范 6.2 不要使用危險的許可與目標組合
規則 6.3 不要禁用字節碼驗證
規則 6.4 禁止部署的應用可被遠程監控
規則 6.5 將所有安全敏感代碼都放在一個jar包中,簽名再加密
規則 6.6 不要信任環境變量的值
規則 6.6 生產代碼不能包含任何調試入口點
7 其他:
規則 7.1 禁止在日志中保存口令、密鑰和其他敏感數據
規則 7.2 禁止使用私有或者弱加密算法
規則 7.3 基於哈希算法的口令安全存儲必須加入鹽值(salt)
規則 7.4 禁止將敏感信息硬編碼在程序中
規則 7.5 使用強隨機數
規則 7.6 防止將系統內部使用的鎖對象暴露給不可信代碼
規則 7.7 使用SSLSocket代替Socket來進行安全數據交互
規則 7.8 封裝本地方法調用