Java中没有真正的二维数组,只有“数组的数组”;不规则二维数组是外层一维引用数组,每个元素指向独立、长度可变的一维int[],内存不连续,需手动逐行初始化并判空访问。

Java 里没有真正的“二维数组”,只有“数组的数组”。不规则二维数组(也叫锯齿数组)正是这种本质最典型的体现:它是一个一维引用数组,每个元素指向一个独立、长度可变的一维 int[],各行内存彼此分离,必须手动控制分配节奏。
结构定义:两步走,不能跳过声明阶段
不规则结构的核心是“行数先定、列数后配”。必须明确区分声明和初始化:
-
声明外层容器:写
int[][] arr = new int[5][];—— 此时只在堆中分配一个含 5 个null引用的一维数组,arr.length是 5,但arr[0]到arr[4]全为null -
逐行初始化子数组:必须显式赋值,例如
arr[0] = new int[3]; arr[1] = new int[7]; arr[2] = new int[1];—— 每次new int[n]都在堆中新开一块连续内存,互不干扰 -
避免误用规则语法:写
new int[5][4]会强制生成 5 行 × 4 列的矩形结构,后续改某一行(如arr[0] = new int[6])只是替换引用,原数组被丢弃,并不改变“规则性”语义
内存空间:两级堆分配,地址不连续
整个结构的数据全部位于堆中,但分两个层级管理:
- 第一级(外层):一块连续内存,存 5 个引用值(即地址),每个指向某一行的起始位置
-
第二级(内层):每行
new int[n]各自申请一段连续内存,这些段之间地址不连续,也不与外层数组相邻 -
栈中只存引用:变量
arr本身在栈中,仅保存外层数组首地址;所有实际数据都在堆里,无栈上数组实体
访问与遍历:判空是铁律,不能假设存在
因为某行可能未初始化(仍为 null),任何对 arr[i] 的直接解引用都可能崩溃:
立即学习“Java免费学习笔记(深入)”;
- 访问前必须检查:
if (arr[i] != null) { ... },否则arr[i][0]或arr[i].length都会抛NullPointerException - 遍历时内层循环不能硬写
j < arr[i].length,必须包裹在判空块内 - 工具方法如
Arrays.toString(arr[i])对null元素直接报错,不可无条件调用
实用初始化方式:一步到位 or 分步控制
两种常见写法效果等价,按场景选:
-
分步初始化:适合动态构造,比如读配置决定每行长度
int[][] arr = new int[4][];<br>arr[0] = new int[2];<br>arr[1] = new int[5];<br>arr[2] = new int[0]; //允许空行<br>arr[3] = new int[3];
-
字面量一步初始化:适合已知全部结构,代码简洁
int[][] arr = {<br> new int[]{1, 2},<br> new int[]{3},<br> new int[]{4, 5, 6},<br> new int[]{7, 8}<br>};


















