System.arraycopy是Java中最底层高效的数组拷贝方式,直接调用JVM本地方法,参数需严格满足索引、长度及类型兼容性约束,否则抛出ArrayIndexOutOfBoundsException或ArrayStoreException。

System.arraycopy 是 Java 中最底层、最高效的数组拷贝方式,它直接调用 JVM 的本地方法(Native),绕过 Java 层的循环和边界检查开销,性能远超 Arrays.copyOf 或手动 for 循环。但它的使用有明确约束,稍不注意就会抛出异常。
参数含义必须记牢:5 个参数各司其职
方法签名:public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
-
src:源数组(不能为空,否则抛
NullPointerException) - srcPos:源数组起始索引(从 0 开始,必须 ≥ 0 且 ≤ src.length)
- dest:目标数组(不能为空,且类型需与 src 兼容)
- destPos:目标数组起始索引(≥ 0 且 ≤ dest.length)
- length:要拷贝的元素个数(≥ 0;若为 0,不报错,静默完成)
任意一个索引越界或 length 导致越界(如 srcPos + length > src.length),都会立即抛出 ArrayIndexOutOfBoundsException。
类型兼容性是硬门槛:不能跨大类赋值
源数组和目标数组的**组件类型(component type)必须兼容**,否则抛 ArrayStoreException:
- 基本类型数组之间严格区分:
int[]不能拷贝到long[],哪怕长度够也不行 - 引用类型遵循继承规则:
String[]可以拷贝到Object[](因为 String 是 Object 子类) - 但
Object[]拷贝到String[]会失败(父类数组不能当子类数组用) - 泛型擦除不影响判断:拷贝
List到[] Object[]是合法的
高效场景推荐:哪些时候该用它?
不是所有拷贝都值得上 arraycopy,它真正发挥价值的地方:
- 大批量数据迁移:例如缓存扩容时将旧数组内容整体搬入新数组
-
实现集合类底层:ArrayList 的
ensureCapacity、removeRange都依赖它做块移动 - 截取/拼接数组片段:比如取 byte[] 的中间 1024 字节,或把两个 char[] 拼成一个
-
避免创建临时包装对象:相比
Arrays.copyOfRange(内部其实也调 arraycopy),自己控制 dest 数组可复用已分配空间
小数据量(如拷贝几个元素)用它反而增加调用开销,意义不大。
常见错误写法与避坑提示
这些错误高频出现,务必警惕:
-
dest 数组长度不足:写成
System.arraycopy(src, 0, dest, 0, src.length)前,没确认dest.length >= src.length -
混淆 srcPos 和 destPos:想从 src 第 2 个元素开始拷 3 个,却写成
srcPos=3(应为 2) - 对 null 数组调用:未判空就直接传参,运行时报 NPE,且堆栈不提示具体哪个参数为空
-
忽略 length 符号:传负数 length 会立即抛异常,而某些计算逻辑(如
end - start)可能意外为负
建议封装一层安全调用工具方法,加入参数校验,尤其在公共库中。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











