Java锯齿数组本质是一维引用数组,外层分配后各元素为null,须逐行手动初始化;内存分两级堆分配,地址不连续;遍历时需判空防NPE,不可用new int3创建伪不规则结构。

Java不规则二维数组(锯齿数组)的内存分配不是一次性完成的,而是分层、手动控制的——它本质上是一维引用数组,每个元素指向独立的一维数组,各自行长度可不同。
先分配外层数组,再逐行初始化
声明时只创建外层容器,不分配实际数据空间:
- int[][] arr = new int[5][];:在堆中分配一个含5个null引用的一维数组,每项尚未指向任何int[]
- 此时arr.length为5,但arr[0]到arr[4]全为null,直接访问arr[0][0]会抛NullPointerException
- 必须显式为每一行赋值,例如:arr[0] = new int[3]; arr[1] = new int[7]; arr[2] = new int[1];……
避免用规则语法误创“假不规则”结构
new int[3][4]会强制生成3×4的矩形数组,所有子数组长度固定为4。后续即使写arr[0] = new int[6],也只是替换引用,原长度为4的数组被丢弃,不会改变整体“规则性”语义。
- 这种写法容易让人误以为在“修改某行长度”,实则是引用替换,不是扩容
- 若目标是真正不规则结构,就不要用new int[行][列]初始化,从一开始就要用new int[行][] + 手动逐行new
遍历时必须判空防崩溃
因为某些行可能未初始化(仍为null),遍历不能默认每行都存在:
立即学习“Java免费学习笔记(深入)”;
- 外层循环用i < arr.length没问题,但内层不能直接用j < arr[i].length
- 必须加判空:if (arr[i] != null) { for (int j = 0; j < arr[i].length; j++) {...} }
- 工具方法如Arrays.toString(arr[i])遇到null会直接抛异常,不可无条件调用
内存布局:两级堆分配,彼此独立
外层数组和每一行子数组都在堆中,但地址不连续:
- 第一级:外层数组本身是一块连续内存,存5个引用(地址)
- 第二级:每行new int[n]各自在堆中开辟一段连续空间,互不相邻,也不依赖外层数组位置
- 栈中只保存arr变量,它指向外层数组首地址;所有数据实体都在堆中


















