審閱了500個PR后,我發現Java開發幾乎都犯了這些錯!
前言:審閱了500個PR后,我帶回了 12 條生存守則
如果你覺得代碼審查只是“看一看改動、點個 Approve”,那多半是因為你還沒遇到那種能讓人懷疑人生的 Pull Request。 在過去的一年里,我親手審過 500+ 個 PR,有些讓我想給作者送錦旗,有些讓我想直接辭職去山里養羊。 今天這篇文章,不是為了吐槽同行,而是為了讓你少走彎路——因為這些坑,幾乎每個 Java 開發都踩過。
我會用真實案例+最佳實踐,幫你梳理 12 個高頻且致命的 Java 編碼錯誤,并告訴你如何在寫代碼時避開它們。
1. 把 Optional 當成花瓶
Optional<String> name = getUserName();
if (name.isPresent()) {
System.out.println(name.get());
}看似“優雅”,實際上只是null 換了個殼。 Optional 不是為了讓你玩 .isPresent() + .get() 套路,而是為了幫你優雅地消滅 null 判斷。
推薦寫法:
getUserName().ifPresent(System.out::println);或者用 map()、orElse() 直接處理值,讓 Optional 真正發揮作用。
記住:如果
.isPresent()是你最熟悉的方法,你用的不是 Optional,而是“希望值”。
2. 接口多到沒人敢動
有些同事寫代碼像是在按“接口生成器”的工資:
public interface IUserServiceFactoryProviderInterface { ... }兩周后,連自己都忘了為什么要這么抽象。
建議規則:重復三次以上再考慮抽象,否則就是在制造理解成本。
每多一個“單實現接口”,就有一個架構師在掉頭發。
3. 流式寫法一開始很優雅,然后失控
好例子:
List<String> names = users.stream()
.filter(u -> u.getAge() > 18)
.map(User::getName)
.sorted()
.toList();壞例子:
users.stream()
.flatMap(g -> g.getMembers().stream())
.collect(Collectors.groupingBy(...))
// 一屏寫不下...當流操作需要配合調試器和流程圖時,你就該停手了。
原則: 復雜邏輯先用可讀的 for 循環,再考慮流式重構。
4. 不經意間改了傳入對象
public void update(User user) {
user.setStatus("INACTIVE");
}這樣寫,調用方的狀態可能被意外篡改,調試起來讓人想摔鍵盤。
更安全的做法:
- 優先返回新對象
- 使用
final修飾 - 不要修改你不擁有的數據
5. 沒有單元測試的改動都是炸彈
“只是個小改動,不用寫測試了”——這種心態是生產事故的溫床。
經驗法則:
- 只要有分支判斷,就必須有測試
- 沒測試,就別指望未來的自己能信任這段代碼
6. 日志要么刷屏,要么寂靜無聲
差的寫法:
System.out.println("進入方法A");
System.out.println("方法A執行中");
System.out.println("退出方法A");或者完全沒日志,讓排查問題像開盲盒。
推薦策略:
- DEBUG → 開發調試
- INFO → 核心業務流程
- ERROR → 異常與關鍵錯誤
- 永遠不要記錄密碼、Token
7. 構造方法長到需要換氣
public UserService(UserRepo repo, EmailService email, Validator val, Logger logger, Clock clock, MetricsRegistry reg, Cache cache, Config cfg, ...) {
...
}如果你的構造方法需要上下滾動才能看完,那它就該被拆了。
解決方案:
- 使用 Builder 模式
- 傳入配置對象
- 按職責拆分服務類
8. 用 == 比對象
if (user.getRole() == Role.ADMIN) // 只有枚舉才適合 ==除了枚舉,其他對象都應該用 .equals()。
9. 拒絕寫注釋不是榮譽勛章
“干凈的代碼不需要注釋”只是理想主義,現實是凌晨 2 點沒人能看懂你的“藝術代碼”。 必要時加簡短注釋,尤其是在業務規則、特殊處理、繞過 bug的地方。
10. 工具類變成了上帝類
StringUtils、DateUtils、EverythingUtils… 當工具類方法比業務類還多時,你已經走上了神化之路。
優化方向:
- 工具類要小而專
- 盡量用領域服務替代巨型工具類
11. 命名風格像萬花筒
String name;
String[] names;
Set<String> name_set;命名混亂會讓讀代碼的人懷疑自己進了平行宇宙。
建議:
- 集合用復數
- 堅持一種命名規范(camelCase/snake_case)
- 少用縮寫,多用有意義的詞
12. 寫給人看的代碼
編譯器不維護代碼,人類才會。 干凈的命名、合理的結構、必要的注釋,都是為了讓下一個接手的人不想掀桌子。
結論:做一個讓別人樂于審查代碼的開發者
你不需要完美無瑕,但你需要足夠用心。
- 不濫用 Optional
- 流式代碼適可而止
- 日志既不刷屏也不沉默
- 有條件分支就寫測試
- 命名一致,注釋簡潔
- 不修改你不擁有的數據
代碼審查不是戰場,但好的代碼會讓審查變成享受。 下次提交 PR 前,先對照這 12 條守則審查一下自己——這樣,你的代碼不僅能更快通過,還能讓團隊更信任你。

























