
一、开场:我被 AI 怼回来的那个下午
上周三,我提交了一个 PR:重构了一个老模块的异常处理逻辑,把一坨 try-catch 嵌套改成了统一的错误边界。自我感觉良好,顺手贴了一段 prompt 给 AI 助手:“Review 一下这段代码,关注错误处理和资源释放。”
结果 AI 回复了整整五条问题,从 “未关闭的数据库连接” 到 “日志打印泄漏敏感信息”,最后一条是:“建议你重新考虑事务范围,当前实现可能导致死锁。”
我盯着屏幕愣了十秒——那条死锁 warning 是我自己硬生生写进去的,因为业务需求要跨两个库做分布式事务,我一时偷懒用了 try-finally 里手动 rollback 的土办法。AI 没讲错,但也没讲全:它知道理论上的“正确姿势”,却不理解我对性能和延迟的取舍。
这就是我今天想聊的:AI 做 code review 不是万能药,用对了是神器,用错了是噪音。
二、AI 代码 review 的四个实战场景
先说结论:我现在每天把 AI review 当成第一道防线,但绝不把它当成唯一的标准。具体来说,有以下四个场景我亲测有效:
| ★★★★★ | ||
| ★★★★☆ | ||
| ★★★★★ | ||
| ★★☆☆☆ |
举个例子:上周我 review 组里新人的 PR,他用了一个
Map 来传递参数,然后用 instanceof 做类型判断。AI 一眼就看出问题:“建议定义明确的类结构,避免类型不安全。” 这种 低级代码坏味道,AI 抓得又快又准,省了我好几分钟。但同样这个 PR,AI 接着评论说:“可以尝试使用策略模式替代 if-else 链。”——这就有点过了。那个场景只有三种状态,硬上策略模式反而增加复杂度。我选择无视。
三、踩过的两个坑:AI 说的不一定都对
坑一:AI 是“原则党”,不是“现实主义者”。
有一次我 review 一个旧系统的性能优化 PR,高手把
for (int i = 0; i < list.size(); i++) 改成了能提少用 list.size() 的 for (String item : list)。AI 评论说:“使用增强 for 循环前,建议预先计算 size 避免重复方法调用。” 我笑了——在 Java 的 ArrayList 里,size() 是 O(1) 操作,根本没有优化价值。AI 只是背了“最小化方法调用次数”的原则,但不懂底层实现。所以我的原则:AI 可以挑刺,但只有我知道哪些刺是真正的刺。
坑二:AI 会“编造”不存在的安全隐患。
某次 AI 警告我用
HttpServletRequest.getParameter() 可能导致“参数污染攻击”,还建议用 getQueryString() 替代。我一头雾水,查了半小时发现根本没有“参数污染攻击”这个标准术语——它把“参数污染攻击”(Parameter Pollution)和“HTTP Parameter Pollution”搞混了,而且后者的攻击面根本不是 Java 侧能解决的。最后我直接在 prompt 里加了“只关注实际风险,不要过度解读”。我给 AI 定了个“review 边界”:只检车,不修路。 它能发现车胎漏气、刹车片磨损,但怎么修、换什么零件,必须我来决定。
四、正确姿势:用 prompt 给 AI 戴上“紧箍咒”
经过半年摸索,我现在每 review 一个 PR,会先写一段 “review 指令模板”,把它粘贴到 AI 对话里,然后粘贴代码。模板长这样:
你是一位资深工程师,正在做代码审查。
请只关注以下方面:
1. 明显的逻辑错误、空指针、死循环
2. 资源未关闭(文件、数据库连接、流)
3. 线程安全和竞态条件
4. 硬编码密码/密钥/URL
5. 跨站脚本(XSS)和 SQL 注入风险
6. 日志中可能泄露的个人信息
请不要对以下方面发表意见:
- 命名风格(除非明显违反团队规范)
- 代码格式、缩进、空行(那是 linter 的工作)
- 设计模式选择(除非严重影响可维护性)
- 业务逻辑变更的合理性(需要理解上下文)
为什么这么写?因为默认情况下,AI 会像刚毕业的大学生:逮住一个冒号就建议改成句号,看谁都像代码坏味道。限定范围能让它从“啰嗦的顾问”变成“精准的质检员”。
有一次我用这个模板 review 了一个涉及多线程的 PR,AI 发现了一个 hidden bug :某个共享变量在
synchronized 块之外被读取 —— 这是典型的“双重检查锁定”误用,但编译器和 JMM 都允许这种写法,一般 review 根本看不到。那一刻我承认:在纯技术细节上,AI 比大多数工程师都细心。五、我心中的 AI code review 工作流
现在我的最终流程是这样的,分享给你:
1. 写代码时: 开一个 AI 侧边栏,丢小段代码问“有没有明显 bug?”——相当于 2 号大脑,秒回。
2. 提交 PR 前: 把完整 diff 扔给 AI(带上面那个模板),它会给我一个列表。我会逐个确认:
- 如果 AI 说“这里可能有空指针”,我就加个 null check。
- 如果 AI 说“建议用
Optional 避免判空”,我可能就忽略——因为团队风格不喜欢过度使用 Optional。3. 人工 review 时: 只看 AI 没提到的部分,尤其是业务逻辑、边界条件、异常处理路径。因为 AI 的盲区就是 “业务上下文”:它不知道我们这个接口的 QPS 是 500 还是 50000,不知道数据库有没有读副本,不知道下游服务允不允许重试。
4. 复盘: 每次被 AI 逮到漏网之鱼,我就把它加进我的 “checklist”(markdown 文件),下次 review 时人工再看一遍。AI 帮我发现了之前习惯性忽略的模式,比如“在 finally 块中关闭资源但忘记处理 close 抛出的异常”。
有朋友问我:这不等于信不过 AI 吗?我说:信得过工具,才需要在岗位上保持清醒。 就像你用计算器算 1+1 不会怀疑它算错,但用它算复合增长率的时候,你总得知道公式对不对。
六、结语:AI 是副驾驶,不是机长
回到开头那个被 AI 怼回 PR 的故事。后来我仔细看了那五条建议,其中三条确实是我疏忽了:一个未释放的 PreparedStatement、一条日志里带了用户邮箱、一个跨库事务的 rollback 没考虑网络超时。我改了代码,AI 闭嘴了。
但那条“可能导致死锁”的警告我保留了——因为我知道那个模块每分钟只调用几十次,而且两个数据库之间延迟在 1ms 以内,死锁概率几乎为零。AI 看到了隐患,但我看到了权衡。
所以,我对 AI code review 的最终判断是:用它来抓低级错误,用它来当第二双眼睛,但永远别用它来替代你的判断力。 毕竟,代码写出来是给人看的,也是给机器跑的——理解和平衡这两者,才是工程师不可替代的核心竞争力。
夜雨聆风