关键是从源头减少无谓的对象创建,尤其避免装箱;应优先使用int、long等基本类型替代Integer、Long等包装类,仅在需null语义或泛型时才用包装类。

避免不必要的对象销毁,关键不是“销毁”本身,而是**从源头减少无谓的对象创建**——因为装箱即创建对象,拆箱不销毁但依赖对象存在,而对象一旦被创建,后续就必然经历分配、可能逃逸、最终被GC回收的过程。所以真正要防的是“不该出现的装箱”。
用原始类型代替包装类
这是最直接有效的做法。只要不需要 null 语义或泛型容器,就别用 Integer、Long、Boolean 等。
- 循环变量、累加器、临时计算值一律声明为 int、long、double 等基本类型
- 方法内部做数值运算时,优先接收 int 而非 Integer;若参数是包装类,先校验非空再转成基本类型使用
- 避免写 Integer sum = 0 或 for (Integer i = 0; i —— 每次自增都隐式拆箱+计算+装箱,生成大量短命对象
集合操作绕过包装类开销
ArrayList
- 高频读写或需计算(求和、过滤、映射)时,改用原生基本类型集合库:Eclipse Collections 的 IntList、Trove 的 TIntArrayList,或直接用 int[]
- Stream 处理整数时,用 IntStream 替代 Stream
,避免中间装箱 - 若必须用标准集合且仅作存储/遍历,可接受;但一旦参与算术或比较,立刻切回基本类型上下文
日志与表达式中切断隐式装箱链
这些地方不显眼,却常在高频路径中反复触发装箱,尤其配合 SLF4J 或三元运算时。
- 日志占位符传参:用 log.info("count: {}", count) 时,确保 count 是 int;若传 Integer,SLF4J 会调用其 toString() 或参与 boxing,产生对象
- 三元表达式如 int x = flag ? obj.getValue() : 0,若 getValue() 返回 null 的 Integer,此处直接 NPE;应改用 Objects.requireNonNullElse(obj.getValue(), 0) 或显式判空
- 方法返回包装类时,调用方若需拆箱,务必先检查是否为 null,不要依赖“它应该不为空”
装箱动作本身也要可控
即使必须用包装类,也要让装箱行为明确、可预测、少开销。
- 统一使用 Integer.valueOf(100)、Boolean.valueOf(true) 等静态工厂方法,它们复用缓存(-128~127),不新建对象
- 绝对禁用 new Integer(100)(JDK 9+ 已废弃),它绕过缓存,每次 new 都是新对象
- 对第三方库或跨模块传入的包装类,不假设其来自 valueOf,始终按可能为 null、可能未缓存来处理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











