Arrays.copyOf核心是两步:先按newLength动态创建新数组,再用System.arraycopy搬运数据;底层由JIT优化为等效native指令,支持默认填充与严格边界控制。

Arrays.copyOf 是 Java 中最常用、最直观的数组复制工具,它不是简单封装一个循环,而是由 JVM 深度优化的高效操作。它的行为看似简单——给定源数组和新长度,就能完成复制、扩容或截断——但背后涉及内存分配策略、JIT 编译介入、类型安全处理以及与 native 层的协同机制。
核心执行流程:两步不可省略
无论数组类型或长度如何,Arrays.copyOf 的逻辑始终分为两个明确阶段:
- 第一步:创建新数组——根据 newLength 和 original.getClass() 动态构造目标数组。基本类型直接 new(如 new int[8]),引用类型通过 Array.newInstance 创建(如 String[].class → new String[8]);跨类型转换时则依据传入的 Class 参数实例化对应容器。
- 第二步:搬运数据——调用 System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)) 完成从头开始的连续拷贝。这一步不支持偏移,也不做元素级深拷贝,只复制值(基本类型)或引用(对象类型)。
底层并非“源码调用”,而是 JIT 内联优化
查看 OpenJDK 源码会发现,某些重载版本确实包含 Java 层循环赋值逻辑(尤其小对象数组),但这只是 fallback 路径。真实高性能场景下,HotSpot JIT 编译器会在方法热执行后将其内联并替换为等效于 System.arraycopy 的本地指令:
- 对 int[]、long[] 等基本类型,通常映射为 CPU 级内存块拷贝(如 SIMD 指令或 Unsafe.copyMemory);
- 对 String[] 等引用类型,大数组走 native 实现,小数组可能展开为数条独立赋值指令以避免调用开销;
- 空数组或长度 ≤ 4 的情况,常被完全编译为字面量初始化,跳过任何运行时分支判断。
默认填充与边界控制由 Java 层严格把关
System.arraycopy 本身不负责填充或校验,这些语义由 Arrays.copyOf 显式实现:
立即学习“Java免费学习笔记(深入)”;
- 若 newLength > original.length,copy 数组中超出原长的部分,按类型自动补默认值:int 填 0、boolean 填 false、引用类型填 null;
- 若 newLength
- newLength 为负数时,直接抛 NegativeArraySizeException,不进入 arraycopy 阶段;
- original 为 null 时,立即触发 NullPointerException,无空值防护逻辑。
适用场景与替代方案对比
选择复制方式不能只看写法简洁,要匹配具体需求:
- 需要扩容/缩容 + 默认填充 → 必选 Arrays.copyOf;
- 仅需等长复制且追求极致性能 → 用 arr.clone(),它跳过参数校验与新数组类型推导,开销最小;
- 要复用已有目标数组、拷贝中间某段、或控制 srcPos/destPos → 只能用 System.arraycopy;
- 想拷贝子区间(如索引 2 到 6)→ 使用 Arrays.copyOfRange,它内部也是先 new 再 arraycopy,但支持起始/结束偏移。


















