arrays.copyof() 不支持动态扩容,仅创建新数组并复制元素;需手动赋值引用才能实现扩容,且要注意类型匹配与合理设置新长度。

Arrays.copyOf() 本身不支持动态扩容,它只做一次性的复制
很多人误以为 Arrays.copyOf() 是个“扩容方法”,其实它只是创建一个新数组、把旧内容拷过去——原数组不会被修改,也不会自动关联到新数组。所谓“动态扩容”,必须由你手动完成:先调用 Arrays.copyOf() 得到新数组,再把引用指向它。
常见错误现象:Arrays.copyOf(arr, newLength) 执行后,arr 还是原来那个小数组,数据没“扩”进去。
- 必须显式赋值:
arr = Arrays.copyOf(arr, newLength); - 如果
arr是方法参数,且没被返回或重新赋值,扩容对外不可见 - 注意类型匹配:泛型数组(如
String[])不能用Arrays.copyOf(Object[], int)直接转,会丢失类型信息,应使用带类型参数的重载
扩容时长度设多少才合理?别硬写固定值
业务中频繁扩容性能差,但一次性开太大又浪费内存。Java 集合类(如 ArrayList)内部用的是“1.5 倍增长”,你可以参考这个策略,而不是每次 +1 或 ×2。
- 推荐公式:
int newLength = Math.max(oldLength + 1, (int)(oldLength * 1.5)); - 避免
newLength ,否则 <code>Arrays.copyOf()返回的还是原数组引用(JDK 优化),起不到扩容作用 - 如果知道后续大概要加多少元素,可预估后一步到位,减少多次复制
基本类型数组和引用类型数组的 copy 行为一致吗?
行为一致:都是浅拷贝。但后果不同,这点容易被忽略。
- 对
int[]、double[]等基本类型:拷贝的是数值本身,安全 - 对
String[]、MyObj[]等引用类型:拷贝的是引用地址,原数组和新数组指向同一堆对象;修改某个元素的内容(如arr[0].field = 1)会影响两边 - 如果需要深拷贝,
Arrays.copyOf()不管用,得自己遍历 +clone()或构造新实例
替代方案:为什么多数场景该直接用 ArrayList?
手写基于 Arrays.copyOf() 的扩容逻辑,本质是在重复造 ArrayList 的轮子。
-
ArrayList内部就是用Object[]+Arrays.copyOf()实现扩容,还做了容量校验、并发安全提示、批量操作优化 - 如果你只需要“增删查”+ “保持插入顺序”,直接用
ArrayList更稳,且 API 清晰(add()自动扩容) - 只有在极少数场景才需手动控制数组:比如高性能计算中规避对象头开销、JNI 交互要求原始数组、或封装底层容器时
真正容易被忽略的点是:扩容不是目的,而是为了支撑后续的业务读写。别为了“看起来在扩容”而提前优化,先确认 ArrayList 的默认行为是否真成了瓶颈。











