Arrays.fill() 仅适用于一维数组的同值填充,对二维数组或需独立对象实例的场景会引发引用共享bug;正确用法是区分数据层与引用层,避免误填导致所有元素指向同一内存地址。

Arrays.fill() 是 Java 中高效初始化数组的利器,但用错地方反而会引发隐蔽 bug。它真正适合的场景是“同值填充”,而不是“构造结构”。关键在于分清一维和二维数组的本质差异——前者填数据,后者填引用。
一维数组:直接、安全、高频使用
这是 Arrays.fill() 最自然的主场。无论是基本类型还是对象数组,只要目标是让所有元素变成同一个值,它就是最简洁的选择。
- 批量设默认值:比如
int[] scores = new int[100]; Arrays.fill(scores, 60);—— 所有学生成绩初始化为 60 分 - 重置布尔标记:如
boolean[] visited = new boolean[n]; Arrays.fill(visited, false); - 局部覆盖:用四参数版本精准修改一段,例如
Arrays.fill(arr, 2, 7, -1);把索引 2 到 6(含)全设为 -1,注意 endIndex 是开区间
二维数组:不能直接填,必须绕道处理
Java 的二维数组本质是“一维引用数组”,每个元素指向一个独立的一维数组。Arrays.fill() 对它作用的是“引用层”,不是“数据层”——填进去的不是数字,而是地址。
- 错误写法:
int[][] grid = new int[5][5]; Arrays.fill(grid, 9);编译失败,因为 9 无法赋给int[]类型 - 更危险的写法:
int[] row = new int[5]; Arrays.fill(row, 9); Arrays.fill(grid, row);表面成功,实则所有行共用同一块内存,改grid[0][0]就等于改了所有grid[i][0] - 正确做法:用循环逐行填充,或先建模板再复制(
Arrays.copyOf()或new int[]{...}),确保每行都是独立实例
对象数组:填的是引用,不是新对象
对 String[]、List[] 等引用类型数组调用 fill,填进去的是同一个对象的多个副本引用。如果后续要修改各元素状态,必须单独 new 实例。
立即学习“Java免费学习笔记(深入)”;
- 安全场景:填 null 或不可变对象(如
Arrays.fill(strings, "N/A")) - 危险场景:
List<String>[] lists = new ArrayList[3]; Arrays.fill(lists, new ArrayList<>());→ 三个索引都指向同一个 ArrayList,add 元素会互相干扰 - 替代方案:用循环或 Stream.generate 创建各自独立的对象实例
性能与可读性权衡
Arrays.fill() 底层是 for 循环,性能和手写循环几乎无差别,但它胜在语义清晰——“我要把这一片全设成这个值”。不过当逻辑复杂(如按行列不同规则初始化)、或需深拷贝时,硬套 fill 反而增加理解成本。
- 简单统一值 → 优先用 fill
- 需要每行不同长度、不同初始值、或对象需独立实例 → 放弃 fill,改用显式循环或 Stream
- 调试时发现“改一个全变”,第一反应应检查是否误用了 fill 初始化二维/对象数组


















