前言:好代碼是寫給人看的
代碼的閱讀次數遠超編寫次數。這三十條規範提煉自《Thinking in Java》等經典與實戰項目血淚,涵蓋命名、類設計、方法規範、異常處理、併發安全、性能權衡、團隊協作等維度。遵循它們,不為「合規」,而為降低認知負荷、減少缺陷、提升可維護性。
命名與格式規範(1-2)
- 命名統一:類 PascalCase、方法/字段 camelCase、常量 UPPER_SNAKE_CASE、包全小寫。
例:UserService、calculateTotalAmount()、MAX_RETRY_COUNT、com.company.module。
- 經典類模板:通用類必覆寫
equals/hashCode/toString,謹慎實現 Cloneable/Serializable,單元測試入口 main() 保留作為使用示例。
方法與類設計原則(3-8)
- 單一職責方法:短小、功能單一、可復用。超過 20 行或嵌套超過 2 層考慮拆分。
- 雙視角設計:面向調用者(API 直觀、文檔完善)與面向維護者(變化點隔離、擴展點預留)。
- 類要小而專:解決一個問題。複雜 switch → 多態;大量類型判斷 → 策略模式;字段語意分組 → 拆分類。
- 最小權限原則:默認
private,按需放寬。多線程下非 private 字段必須同步或用線程安全類。
- 拒絕上帝對象:順序邏輯別塞進大類。對象表達領域概念,而非流程腳本。
- 醜陋代碼隔離:不得已的 Hack 封裝在內部類/私有方法,不污染公共 API。
耦合與內部類(9-10)
- 內部類解耦:緊耦合類群改用非靜態內部類訪問外部狀態,或靜態內部類作為實現細節隱藏。
文檔與魔術數字(11-12)
- Javadoc 文檔化:公共 API 必寫 @param/@return/@throws/@see,包含用法示例。
- 消除魔術數字:
if (size > 100) → if (size > MAX_CACHE_SIZE),語義自證,修改單點。
構造器與異常處理(13-16)
- 構造器失敗快速失敗:捕獲異常拋出運行時異常,避免半初始化對象流出。
- 顯式清理契約:需釋放資源的類提供
close()/shutdown(),配合 try-with-resources 或 finally 塊,finalize() 只作最後防線並拋出錯誤日誌。
- 初始化即清理:
Resource r = new Resource(); try { ... } finally { r.close(); } 模式保證釋放。
- finalize 調用超類:
super.finalize() 放最後,確保基類資源仍可用時釋放。
集合與接口導向(17-18)
- 固定大小集合返回數組:編譯期類型安全,調用者無需強轉。
- 優先接口而非抽象類:接口定義「做什麼」,類實現「怎麼做」。只有需要共享代碼/狀態時才用抽象類。
構造器與繼承陷阱(19-22)
- 構造器不調用可覆寫方法:子類覆寫會導致父構造器見到未初始化的子類狀態。
- 對象要有行為:純數據容器用 Record (JDK 14+) 或 DTO,領域對象封裝業務不變量。
- 組合優於繼承:預設用「新建/委派」,只有滿足 Liskov 替換原則(is-a 關係)才繼承。
- 狀態用字段,行為用多態:顏色用
Color color 字段,別搞 RedCar extends Car。
類路徑與事件陷阱(23-24)
- 類名全局唯一:類路徑下同名類導致不可預期加載。善用
mvn dependency:tree 排查衝突。
- AWT 適配器拼寫陷阱:覆寫
mouseClicked 寫成 mouseClick 不報錯卻不生效。用 @Override 強制編譯器檢查。
單例與過度設計(25-27)
- 單例模式替代「只創建一個」註釋:私有構造器 + 靜態工廠 + 枚舉實現(防序列化破壞、防反射攻擊)。
- 拒絕分析癱瘓:先掌握全局上下文,再深入細節,避免陷入死邏輯。
- 過早優化是萬惡之源:先跑通、再測量、有瓶頸再優化。Profiler 比直覺靠譜。
代碼審查與團隊文化(28-30)
- 代碼寫給未來的自己和同事:清晰命名、必要註釋、示例測試,比任何文檔都管用。
- 引入新鮮眼光審查:跨團隊/新人 Code Review 常發現盲區,修復成本最低。
- 良好設計回報最高:前期投入架構思考,後期輕鬆擴展。拒絕「先跑起來再重構」的技術債循環。
總結
這三十條不是教條,而是經驗提煉的護欄。團隊可據此建立 Checkstyle/SpotBugs/SonarQube 規則集,納入 CI 橋接,將規範內化為「不經思考的肌肉記憶」。記住:代碼質量不是靠事後檢查進來的,是寫出來的。