【Java踩坑笔记】52_总结篇:Java踩坑的10条黄金法则

📅 2026/7/19 0:37:23 👁️ 阅读次数 📝 编程学习
【Java踩坑笔记】52_总结篇:Java踩坑的10条黄金法则

52 | 总结篇:Java 踩坑的 10 条黄金法则

摘要:52 篇文章、8 个辑、覆盖 Java 基础到生产实战。本文把最核心的 10 条法则提炼出来,方便你记忆和团队分享。


一、黄金法则(背诵版)

法则 1:对象比较,一律用equals

基本类型(int、long...)→ 用 == 引用类型比较"值相等" → 用 equals String 比较 → 永远 equals,别用 == 包装类型(Integer、Long...)→ equals 或先拆箱

相关文章:第 01 篇


法则 2:浪费BigDecimal禁止用double构造#

new BigDecimal(0.1) → ❌ 精度已丢失 new BigDecimal("0.1") → ✅ 正确 BigDecimal.valueOf(0.1) → ✅ 正确(内部先转 String)

相关文章:第 03 篇


法则 3:synchronized锁定的是对象,不是代码块#

String、Integer、Boolean 不要做锁对象(可能共享) 锁对象必须是 private final 的 缩小锁范围:只包住需要互斥的代码

相关文章:第 16 篇


法则 4:i++不是原子操作,高并发用Atomic类#

i++ → 读 → 改 → 写(三步,不是原子) 低并发 → AtomicInteger 高并发 → LongAdder(Java 8+)

相关文章:第 18 篇


法则 5:@Transactional自调用不生效,必须拆 Service#

同一个类里调用 @Transactional 方法 → ❌ 不生效 拆到另一个 Service → ✅ 经过代理 Exception 类型 → 必须指定 rollbackFor = Exception.class

相关文章:第 32 篇


法则 6:集合框架,先想清楚再选#

List 查多改少 → ArrayList List 头插/头删多 → LinkedList Map 高频查找 → HashMap Map 需要排序 → TreeMap 并发 Map → ConcurrentHashMap

相关文章:第 09 ~ 15 篇


法则 7:线程池,禁止用Executors创建#

✅ 用 ThreadPoolExecutor 手动创建 ✅ 队列必须有界(防止 OOM) ✅ IO 任务用独立线程池(别占满 commonPool) ✅ 提交任务必须处理异常(submit 后必须 get)

相关文章:第 19、20、24 篇


法则 8:JVM 参数,不只设-Xmx#

-Xmx 只限制堆 Metaspace → -XX:MaxMetaspaceSize DirectBuffer → -XX:MaxDirectMemorySize 容器化 → -XX:+UseContainerSupport(JDK 8u191+)

相关文章:第 29 篇


法则 9:MyBatis 能用#{}就不用${}#

#{} → ? 占位符,预编译,安全 ✅ ${} → 字符串替换,有注入风险 ❌ 动态表名用 ${} 时,必须白名单校验

相关文章:第 41 篇


法则 10:生产问题,保留现场优先于重启#

OOM → -XX:+HeapDumpOnOutOfMemoryError(自动 dump) 死锁 → jstack <pid> > dump.txt(保留线程堆栈) 慢查询 → 开慢查询日志(slow_query_log) 重启前 → 一定先 dump 现场!

相关文章:第 50、51 篇


二、记忆卡片(速查)#

第一辑:基础语法篇(8 篇)#

核心记忆点一句话
== vs equals== 比地址,equals 比值
自动拆箱包装类型运算前必须判空
BigDecimal禁止用 double 构造
String +循环内拼接必须用 StringBuilder
equals + hashCode必须同时重写,否则 HashMap 失效
try-finallyfinally 里别写 return
泛型擦除运行期拿不到泛型类型
枚举 ordinal别用,用自定义 code 字段

第三辑:并发编程篇(10 篇)#

核心记忆点一句话
synchronized锁定对象,不是代码块
volatile保证可见性,不保证原子性
i++不是原子操作
线程池 submit异常被吞,必须 get()
线程池队列必须有界,防止 OOM
CountDownLatchcountDown() 必须放 finally
ThreadLocal用完必须 remove(),防止泄漏
DCL 单例必须加 volatile
CompletableFuture生产环境必须指定自定义线程池
锁选型简单用 synchronized,高级用 ReentrantLock

三、团队落地建议#

3.1 代码评审 Checklist#

把这份 Checklist 加入团队的 PR 模板:

Java 代码评审 Checklist(踩坑预防版) □ 1. 字符串比较是否用了 equals?(禁止 ==) □ 2. BigDecimal 是否用了 String 构造?(禁止 double 构造) □ 3. 包装类型参与运算前是否判空?(防止 NPE) □ 4. 重写 equals 是否同时重写了 hashCode? □ 5. ArrayList 循环删除是否用了 removeIf?(禁止 foreach 里 remove) □ 6. 线程安全类是否选对了?(ConcurrentHashMap vs HashMap) □ 7. 锁对象是否是 private final 的?(禁止 String/Boolean 做锁) □ 8. i++ 在并发场景下是否用了 AtomicInteger? □ 9. @Transactional 方法是否是 public 的?是否避免了自调用? □ 10. 线程池是否用 ThreadPoolExecutor 手动创建?(禁止 Executors) □ 11. 提交到线程池的任务内部是否有 try-catch? □ 12. ThreadLocal 是否在 finally 里 remove() 了? □ 13. @Async 方法是否加了 @EnableAsync?是否避免了自调用? □ 14. MyBatis 的 SQL 是否用了 #{}?(禁止用 ${} 拼 WHERE 条件) □ 15. 分页查询偏移量是否超过了 10000?(超过了要用延迟关联优化) □ 16. 生产环境 -Xmx 是否同时配了 MaxMetaspaceSize 和 MaxDirectMemorySize? □ 17. 日志打印对象时,toString() 是否可能递归? □ 18. 用 SimpleDateFormat 的地方是否线程安全?(建议迁移到 DateTimeFormatter) □ 19. 实现 Serializable 的类是否写了 serialVersionUID? □ 20. OOM 参数是否加了 -XX:+HeapDumpOnOutOfMemoryError?

3.2 IDEA 必装插件#

插件作用
Alibaba Java Coding Guidelines扫描阿里开发手册规约
SonarLint静态代码分析,提前发现 bug
MyBatisXMyBatis XML 和 Mapper 互跳,警告 ${} 风险
Lombok减少样板代码,自动生成 *ArgsConstructor

3.3 新人入职培训#

把前 8 篇(基础语法篇)作为新人必读,要求:

  1. 通读 8 篇文章
  2. 每篇文章后面附 3 道选择题(自测)
  3. 排入新人入职第一周的培训计划

四、专栏使用建议#

4.1 作为团队知识库#

建议存放位置: - 腾讯文档(方便协作、搜索) - 公司内网 Wiki(Confluence / 飞书文档) - 个人博客(Hexo / Hugo,SEO 友好)

4.2 持续更新#

Java 在演进,坑也在变化。建议:

  • 每遇到一个新坑,写一篇新文章
  • Java 新版本(每 6 个月一个 LTS)发布后,检查是否有新的踩坑场景
  • 读者留言里的高频问题,补充到对应文章里

4.3 配套练习#

建议为每篇文章写一个「课后练习」(JUnit 测试),让读者运行测试时直观感受 bug:

// 第 01 篇配套练习@TestpublicvoidtestStringComparison(){Strings1=newString("hello");Strings2="hello";assertFalse(s1==s2);// 预期:== 比较失败assertTrue(s1.equals(s2));// 预期:equals 成功}

五、结语#

踩坑不可怕,可怕的是在同一个坑里跌倒两次。

这份专栏的目标,是让你把「不知道有这个坑」变成「我知道这里有坑,绕过去」。

Java 还在演进,新的坑会不断出现。保持好奇心,保持对底层原理的追问,你就能在大部分坑出现之前就识别它们。

祝编码愉快,生产环境 0 Bug。🎉


全专栏完。52 篇文章,8 个辑,祝你踩坑越来越少。


附录:文章索引(快速查阅)#

文章范围核心主题
第一辑:基础语法篇01 ~ 08== vs equals、BigDecimal、String+、枚举 ordinal
第二辑:集合框架篇09 ~ 15CME、HashMap 扩容、HashSet 可变对象、Stream 并行流
第三辑:并发编程篇16 ~ 25synchronized、volatile、i++、线程池、ThreadLocal、DCL、CompletableFuture
第四辑:JVM 与性能篇26 ~ 31toString 递归、反射性能、finalize、OOM、Soft/Weak Reference、Lambda this
第五辑:Spring/Spring Boot 篇32 ~ 39@Transactional、Field 注入、@Async、@Value、循环依赖、AOP、配置加载
第六辑:数据库与 MyBatis 篇40 ~ 44PreparedStatement null、#{} vs ${}、连接池、LIMIT 优化、保留字
第七辑:日常开发技巧篇45 ~ 49日志 toString、switch 穿透、SimpleDateFormat、Optional、serialVersionUID
第八辑:综合实战篇50 ~ 52OOM 排查、死锁定位、总结篇