锯齿数组先声明外层数组确定行数,每行再单独分配长度,支持不等长且节省内存;声明时各行为null,需逐行初始化,访问前须判空并用arr[i].length获取实际长度。

锯齿数组不是一次性铺开的矩形结构,而是“先搭架子、再填内容”——外层数组先声明行数,每行再单独分配长度。这种一行一行构建的方式,正是它灵活、节省内存的关键。
声明外层数组:只定行数,不设列数
先用 int[][] arr = new int[行数][]; 声明一个引用数组,其中每个元素初始为 null,不代表空数组,而是尚未指向任何实际内存。
- 例如:int[][] grid = new int[4][]; 表示准备了 4 个“槽位”,但每个槽都空着
- 此时 grid.length == 4,但 grid[0] 直接访问会抛出 NullPointerException
逐行初始化:按需分配每一行的长度
对每一行单独执行 new int[该行元素个数],可自由设定不同长度,也可立即赋初值。
- grid[0] = new int[2]; → 第 0 行有 2 个 int,默认值为 0
- grid[1] = new int[]{7, 8, 9}; → 第 1 行直接初始化为含 3 个元素的数组
- grid[2] = new int[5]; → 第 2 行长度为 5,全为 0
- 跳过某行(如不赋值 grid[3])则保持 null,后续访问前必须判空
常见写法对比:一步到位 vs 分步构建
两种方式本质相同,选哪种取决于代码可读性与初始化时机:
- 分步构建:适合运行时动态决定每行长度(比如读取文件后逐行解析)
- 字面量初始化:int[][] data = { new int[]{1}, new int[]{2,3}, new int[]{4,5,6} }; 更紧凑,编译期确定结构
安全访问:每行长度独立,必须动态检查
不能假设所有行等长,遍历时必须用 arr[i].length 获取当前行真实长度。
- 错误写法:for (int j = 0; j (其他行可能更短或更长)
- 正确写法:for (int i = 0; i











