Java多维数组是“数组的数组”,外层数组仅存储指向独立子数组的引用,各子数组在堆中非连续分配且长度可不同;访问arri需两次解引用,体现两级嵌套结构。

Java 中的多维数组不是一块连续内存上的“表格”,而是一个一维引用数组,它的每个元素都指向另一个独立的一维数组——也就是“数组的数组”。
外层数组只存地址,不存数据
声明 int[][] arr = new int[3][] 时,JVM 只在堆上分配一个长度为 3 的一维数组,类型是 int[],每个位置初始值都是 null。它不包含任何整数,也不预留子数组空间。
- 就像准备了 3 个空信封,每个信封上写着“这里放一个 int[]”
- 真正装数字的子数组(如
new int[4]、new int[7])要后续单独创建 - 这些子数组各自在堆中任意位置分配,彼此物理地址不连续,长度互不影响
不规则结构是自然结果,不是特例
你可以让每行长度不同,甚至某行为 null 或空数组,这完全合法:
-
arr[0] = new int[2];→ 分配 2 个 int 的连续空间 -
arr[1] = new int[5];→ 另起一块 5 个 int 的连续空间,和前一块无关 -
arr[2] = null;或arr[2] = new int[0];都不会影响其他行
这种灵活性正源于外层数组只是“导航索引表”,不是数据容器。
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
访问需两次解引用,暴露嵌套本质
写 arr[1][3] 时,JVM 实际执行两步:
- 先查外层数组第 1 个槽位:
arr[1]→ 得到一个指向某块内存的引用(比如地址0x7a2f) - 再用这个地址 + 偏移量访问第 3 个元素:
*(0x7a2f + 3×4)
中间有一次间接跳转,说明这不是单块内存上的线性偏移(如 C 的 int a[3][5]),而是明确的“先找数组,再找元素”的两级结构。
和 C/C++ 连续布局对比鲜明
C 中 int a[2][3] 是栈上一块连续 6 个 int 的内存;Java 的 int[2][3] 写法只是语法糖,底层仍是:
- 一个长度为 2 的
int[]引用数组 - 两个分别长度为 3 的
int[]数据数组 - 三块内存可能分散在堆的不同页中
所谓“规则矩形数组”,不过是所有子数组恰好长度一致的巧合而已。

















