Arrays.fill 是就地填充操作,时间复杂度 O(n)、空间复杂度 O(1),通过循环赋值实现,支持基本类型和引用类型数组,但引用类型会共享同一对象;提供多种重载方法控制填充范围,不触发 GC;与 setAll 的静态填充 vs 动态生成有本质区别;需注意引用共享和线程安全问题。

Arrays.fill 并不创建新数组,而是直接在原数组内存区域写入指定值,属于“就地填充”,时间复杂度 O(n),空间复杂度 O(1)。
fill 的底层实现本质是顺序赋值
它没有调用 native 方法或内存拷贝指令,而是通过一个简单循环遍历索引范围,逐个执行 array[i] = value。JVM 会对此类连续写操作做优化(如自动向量化),但语义上仍是普通字段赋值。
- 对基本类型数组(如 int[]、double[]),直接写入对应二进制值
- 对引用类型数组(如 String[]),写入的是同一引用地址(即所有元素指向同一个对象)
- 不会触发 GC,也不改变数组对象的堆地址和长度
重载方法决定填充范围与类型适配
Arrays.fill 提供多种重载,关键区别在于起始/结束索引和泛型约束:
- fill(int[] a, int val):填充整个数组
- fill(int[] a, int fromIndex, int toIndex, int val):仅填充 [fromIndex, toIndex) 区间(左闭右开)
- fill(Object[] a, Object val):要求 val 类型与数组组件类型兼容,否则运行时抛 ClassCastException
注意:toIndex 超出数组长度会抛 IndexOutOfBoundsException;fromIndex > toIndex 则不执行任何操作。
立即学习“Java免费学习笔记(深入)”;
与 Arrays.setAll 的核心区别
fill 是“静态值填充”,setAll 是“动态函数生成”:
- fill 使用固定值,适合初始化为默认状态(如全 0、null、false)
- setAll 接收 IntUnaryOperator 或 Function,可按索引计算不同值(如 fill 无法实现 i² 序列,setAll 可以)
- setAll 有额外函数调用开销,但灵活性高;fill 更轻量、更易预测性能
实际使用中的常见误区
容易忽略类型擦除和引用共享问题:
- 对 Integer[] 执行 fill(arr, 42),每个元素是新创建的 Integer(42) 吗?不是 —— 实际复用 Integer.valueOf(42) 缓存对象,所有元素引用相同实例
- 对自定义对象数组 fill(arr, new User("A")),所有元素将指向同一个 User 实例,修改任一元素属性会影响全部
- 多线程环境下,若多个线程同时 fill 同一数组,需自行同步,fill 本身不保证原子性


















