system.arraycopy本身不扩容,仅高效搬运数据;真正扩容需闭环执行“判断→分配→搬运→更新”四步:先计算新容量(如math.max(size+1, (int)(oldcap*1.5))),再new分配新数组,接着arraycopy拷贝size个有效元素,最后更新引用及状态。

System.arraycopy 本身不扩容,它只做一件事:高效搬运数据。真正实现高效扩容,关键在于把它嵌入一个轻量、可控、可复用的流程中——不是写一次 arraycopy 就完事,而是把“判断→分配→搬运→更新”四步串成闭环。
扩容必须分两步:分配新数组 + 搬运有效数据
Java 数组长度固定,无法就地变长。每次扩容本质是:
- 计算新容量(例如:Math.max(size + 1, (int)(oldCap * 1.5)))
- 用 new int[newCap] 或 new Object[newCap] 分配一块新的连续内存
- 调用 System.arraycopy(src, 0, dest, 0, size) 把当前有效的 size 个元素一次性搬过去
- 最后更新引用:array = newArr,并同步维护 size 和容量状态
搬运长度必须是 size,不是 length
这是最常出错的地方。常见错误是写成 arraycopy(src, 0, dest, 0, dest.length),这会把默认值(如 0、null)也复制进去,污染后续逻辑。
正确做法是:
- 源起始位置始终为 0
- 目标起始位置也从 0 开始(追加场景)
- 拷贝长度严格等于当前已存元素数 size,不是原数组
length,更不是新数组length - 例如:原数组有 7 个元素(size = 7),即使
length是 10,也只拷前 7 个
推荐扩容策略:1.5 倍增长 + 最小保障
避免频繁扩容和内存浪费,建议采用类似 ArrayList 的策略:
- 新容量 = Math.max(oldCap + 1, (int)(oldCap * 1.5))
- 初始容量设为 8 或 16,防止小数组反复扩
- 提供 ensureCapacity(int min) 方法,供调用方预判,避开临界点性能毛刺
- 对中等规模数据,1.2~1.5 倍比固定 ×2 更省内存
封装成方法更安全、易复用
直接裸写 arraycopy 容易漏掉判断或写错长度。封装后既隐藏细节,又便于统一控制:
- 基础版(int[]):public static int[] grow(int[] src, int minCapacity),内部完成计算、创建、搬运、返回
- 泛型友好版:用 Object[] 存储,get 时强转;或构造时传 Class,用 Array.newInstance(clazz, newCap) 创建类型化数组
- 日常开发可直接用 Arrays.copyOf(arr, newLength),它底层就是封装好的 arraycopy,还自带空值/负长防护











