装箱性能损耗主要源于对象创建开销和缓存边界效应;缓存范围内(如Integer -128~127)复用对象,范围外则new对象引发堆分配、初始化及GC压力,单个Integer对象约24字节,远超int的4字节。

装箱带来的性能损耗主要来自对象创建开销和缓存机制的边界效应,不是每次装箱都慢,但某些场景下会明显拖慢程序。
装箱本质是调用 valueOf() 创建对象
自动装箱(比如 Integer a = 100)在编译后实际等价于 Integer a = Integer.valueOf(100)。这个方法不总是新建对象:
- 数值在缓存范围内(如
Integer是 -128 到 127),直接返回缓存中的已有对象,几乎无开销; - 数值超出缓存范围(如
Integer a = 2000),valueOf()内部会执行new Integer(2000),触发堆内存分配、对象初始化、GC 压力; - 每次新建对象还包含对象头(约 12 字节)、对齐填充(HotSpot 通常补到 8 字节倍数),实际一个
Integer对象占约 24 字节,而原始int只占 4 字节。
高频装箱场景容易暴露问题
以下写法看似简洁,实则可能频繁创建临时对象:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 在循环中反复装箱:比如
for (int i = 0; i (<code>list是ArrayList<integer></integer>),i 每次都被装箱为新Integer; - 用包装类做计算中间变量:如
Integer sum = a + b(a、b 是Integer),先拆箱、相加、再装箱,三次对象操作; - 日志或字符串拼接中隐式装箱:如
log.info("value=" + obj.getValue()),若getValue()返回Integer,拼接时会触发toString(),内部也可能涉及装箱逻辑。
对比基本类型能直观看出差异
以存储百万整数为例:
立即学习“Java免费学习笔记(深入)”;
- 用
int[]:约占用 4 × 10⁶ = 4 MB; - 用
ArrayList<integer></integer>:每个Integer对象约 24 字节,加上ArrayList底层数组引用、扩容冗余,总内存可能达 30 MB 以上; - 不止内存高,GC 频率也会升高,尤其在短生命周期大量装箱时,容易触发 Young GC。
规避建议很务实
不需要彻底禁用装箱,而是有意识地避开高成本用法:
- 集合操作优先考虑原始类型库(如 Eclipse Collections、Trove、FastUtil),它们提供
IntList等专用结构; - 循环内避免把基本类型反复赋给包装类变量,能用
int就别用Integer做中间计算; - 明确需要 null 语义时才用包装类,否则一律用基本类型;
- 排查性能瓶颈时,用 JFR 或 VisualVM 观察
Integer对象的分配速率,确认是否真由装箱引起。


















