二维数组创建的对象数量取决于初始化方式:new int3创建4个对象,new int[3][]仅创建1个外层数组,后续按需new内层才增加对象;每个new调用生成独立数组对象,基本类型不产生新对象。

Java二维数组的内存占用和垃圾回收不是两个孤立问题,而是一体两面:你分配了多少对象,就可能回收多少对象;每个对象占多少空间,决定了GC压力大小。关键不在“几维”,而在“new了几次”。
二维数组实际创建几个对象?
答案取决于初始化方式,不是固定值:
- int[][] arr = new int[3][4]; → 创建4个对象:1个外层数组(长度3)+ 3个内层数组(每个长度4)
- int[][] arr = new int[3][]; → 只创建1个对象(外层数组),内层全为null,没new就不占堆空间
- arr[0] = new int[2]; arr[2] = new int[5]; → 总共3个对象(1外层 + 2已初始化的内层)
记住:每个 new 调用都生成一个独立数组对象;基本类型(如int)不产生对象,只占数组内部存储空间。
内存占用怎么算?
以 new int[3][4] 为例:
- 外层数组:对象头 + 3个引用字段(每个引用在64位JVM通常占8字节,压缩OOP下可能4字节)
- 每个内层数组:对象头 + 长度字段 + 4个int(4×4=16字节)
- int本身不额外开销,但数组对象头(约12–16字节)、对齐填充、引用字段都会叠加
粗略估算:1个外层数组约40–64字节,3个内层数组各约32–48字节,总内存约140–210字节(不含JVM内部管理开销)。真实值需用JOL(Java Object Layout)工具验证。
null赋值后,哪些对象真能被回收?
设 arr = null; 后能否回收,只看是否还有强引用指向它们:
- 若只有
arr持有外层数组,且没保存过arr[i]到其他变量 → 4个数组对象全部符合回收条件 - 若曾执行
int[] row = arr[1];→ 外层数组和另外两个内层数组可回收,row引用的那1个内层数组仍存活 - 若内层数组被放进静态集合或作为参数传入长期存活对象 → 它们将一直留在堆中,成为潜在内存泄漏点
null只是切断引用链起点,真正决定回收的是可达性分析结果,不是赋值动作本身。
实战优化建议
处理大二维数组时,别只盯着元素数量,要盯对象数量:
- 用
new int[rows][]+ 按需初始化内层,避免一次性创建大量空数组 - 及时置null不是必须操作,但对长生命周期引用(如类字段、缓存)很有必要
- 考虑用一维数组模拟二维(
data[row * cols + col]),减少对象数,提升GC效率 - 监控时关注 Young GC频率 和 promotion rate,高频晋升说明短生命周期数组正在拖慢系统
理解这个机制,不是为了凑出“回收4个”的答案,而是让每一块堆内存都用得明白、放得干脆。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











