优化核心是让对象生命周期可控、复用自然、分配高效:优先循环外声明+重置复用(如stringbuilder.setlength(0)),对高成本对象池化,避免隐式装箱与动态扩容。

循环体内频繁 new 对象,本质是把轻量操作做成了重量负担——对象分配、初始化、GC 回收三重开销叠加,尤其在高吞吐场景下极易引发内存抖动甚至 OOM。优化核心不是“少写 new”,而是让对象生命周期更可控、复用更自然、分配更高效。
优先复用局部变量,避免逃逸
如果对象只在当前方法内使用,且不被返回、不被存入集合或静态字段,JVM 有可能通过逃逸分析将其分配在栈上(TLAB 分配 + 栈上分配优化)。即便未触发逃逸分析,控制其作用域也能缩短存活时间,降低年轻代 GC 压力。
- 不推荐:每次循环都 new 一个新 ArrayList 或 StringBuilder
- 推荐:在循环外声明,循环内 clear() 或 setLength(0),重置状态继续用
- 示例:StringBuilder sb = new StringBuilder(512); for (int i = 0; i
轻量对象按需池化,重量对象必须池化
对象池不是银弹,但对创建成本高(如含 IO、反射、复杂初始化)或数量稳定可预期的对象非常有效。关键判断标准是:单次 new 的耗时是否显著高于 pool.acquire() + use + release() 的总开销。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 适合池化:数据库连接、HTTP 客户端实例、带缓存逻辑的解析器、自定义缓冲区类
- 慎用池化:仅含几个 int 字段的 DTO,new 开销远低于池管理成本
- 可用工具:Apache Commons Pool、Netty 的 Recycler(专为 Netty 场景优化)、或 JDK 9+ 的 VarHandle 实现无锁轻量池
用基本类型替代包装类,绕过装箱开销
循环中用 Integer、Long 做计数器或中间计算,会隐式触发大量自动装箱,生成无数短命对象。这不是“创建业务对象”,但危害一样大。
- 错误写法:Integer sum = 0; for (int i = 0; i
- 正确写法:int sum = 0; for (int i = 0; i
- 集合场景若必须用泛型,优先考虑 Trove、Eclipse Collections 等提供原始类型集合的库,避免 Integer[] 背后隐藏的 boxed 对象数组
预分配容量 + 避免隐式扩容
ArrayList、HashMap、StringBuilder 等动态结构,在循环中反复 add/put/append 会触发多次扩容,每次扩容都伴随数组复制和新对象分配,放大内存压力。
- 明确大小时:new ArrayList(expectedSize)、new HashMap(expectedSize)、new StringBuilder(expectedCapacity)
- 大小不确定但有上限:按上限预估,宁稍大勿频繁扩
- 特别注意:ArrayList 的默认扩容是 1.5 倍,10 万次 add 若未预设,可能产生 10+ 次数组复制和临时数组对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










